Commit a070b434 authored by Niels Möller's avatar Niels Möller
Browse files

New files reaper.h and reaper.c.

Rev: src/Makefile.in:1.25
Rev: src/reaper.c:1.1
Rev: src/reaper.h:1.1
parent a55f6f23
...@@ -45,7 +45,7 @@ COMMON_SRCS = alist.c atoms.c bignum.c channel.c \ ...@@ -45,7 +45,7 @@ COMMON_SRCS = alist.c atoms.c bignum.c channel.c \
CLIENT_SRCS = lsh.c client.c client_keyexchange.c \ CLIENT_SRCS = lsh.c client.c client_keyexchange.c \
client_password.c client_userauth.c client_password.c client_userauth.c
SERVER_SRCS = lshd.c server.c server_keyexchange.c\ SERVER_SRCS = lshd.c reaper.c server.c server_keyexchange.c\
server_password.c server_userauth.c server_password.c server_userauth.c
SRCS = $(COMMON_SRCS) $(CLIENT_SRCS) $(SERVER_SRCS) SRCS = $(COMMON_SRCS) $(CLIENT_SRCS) $(SERVER_SRCS)
......
/* reaper.c
*
* Handle child processes.
*
* $Id$
*/
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Niels Mller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "reaper.h"
#include "alist.h"
#include "werror.h"
#include "xalloc.h"
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
static sig_atomic_t halloween;
static void child_handler(int signum)
{
assert(signum == SIGCHLD);
halloween = 1;
}
struct reaper
{
struct reap super;
/* Mapping of from pids to exit-callbacks. */
/* NOTE: This assumes that a pid_t fits in an int. */
struct alist *children;
};
static void do_reap(struct reap *c,
pid_t pid, struct exit_callback *callback)
{
struct reaper *closure = (struct reaper *) c;
MDEBUG(closure);
assert(!ALIST_GET(closure->children, pid));
ALIST_SET(closure->children, pid, callback);
}
/* FIXME: Use an alist of pids->callbacks */
static void reap(struct reaper *r)
{
pid_t pid;
int status;
/* We must reset this flag before reaping the zoombies. */
halloween = 0;
while( (pid = waitpid(-1, &status, WNOHANG)) )
{
if (pid > 0)
{
int signaled;
int value;
int core;
struct exit_callback *callback;
if (WIFEXITED(status))
{
verbose("Child %d died with exit code %d.\n",
pid, WEXITSTATUS(status));
signaled = 0;
core = 0;
value = WEXITSTATUS(status);
}
else if (WIFSIGNALED(status))
{
verbose("Child %d killed by signal %d.\n",
pid, WTERMSIG(status));
signaled = 1;
core = !!WCOREDUMP(status);
value = WTERMSIG(status);
}
else
fatal("Child died, but neither WIFEXITED or WIFSIGNALED is true.\n");
callback = ALIST_GET(r->children, pid);
if (callback)
{
ALIST_SET(r->children, pid, 0);
EXIT_CALLBACK(callback, signaled, core, value);
}
else
{
if (WIFSIGNALED(status))
werror("Unregistered child %d killed by signal %d.\n",
pid, value);
else
werror("Unregistered child %d died with exit status %d.\n",
pid, value);
}
}
else switch(errno)
{
case EINTR:
werror("reaper.c: waitpid() returned EINTR.\n");
break;
case ECHILD:
/* No more child processes */
return;
default:
fatal("reaper.c: waitpid failed (errno = %d), %s\n",
errno, strerror(errno));
}
}
}
struct reaper *make_reaper(void)
{
struct reaper *closure;
NEW(closure);
closure->super.reap = do_reap;
closure->children = make_linked_alist(0, -1);
return closure;
}
/* FIXME: Prehaps this function should return a suitable exit code? */
void reaper_run(struct reaper *r, struct io_backend *b)
{
struct sigaction pipe;
struct sigaction chld;
pipe.sa_handler = SIG_IGN;
sigemptyset(&pipe.sa_mask);
pipe.sa_flags = 0;
pipe.sa_restorer = NULL;
chld.sa_handler = child_handler;
sigemptyset(&chld.sa_mask);
chld.sa_flags = SA_NOCLDSTOP;
chld.sa_restorer = NULL;
if (sigaction(SIGPIPE, &pipe, NULL) < 0)
fatal("Failed to ignore SIGPIPE.\n");
if (sigaction(SIGCHLD, &chld, NULL) < 0)
fatal("Failed to install handler for SIGCHLD.\n");
halloween = 0;
while(io_iter(b))
if (halloween)
reap(r);
}
/* reaper.h
*
* Handle child processes.
*
* $Id$
*/
/* lsh, an implementation of the ssh protocol
*
* Copyright (C) 1998 Niels Möller
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef LSH_REAPER_H_INCLUDED
#define LSH_REAPER_H_INCLUDED
#include "io.h"
struct exit_callback
{
struct lsh_object header;
void (*exit)(struct exit_callback *closure,
int signaled, int core, int value);
};
#define EXIT_CALLBACK(e, s, c, v) ((e)->exit((e), (s), (c), (v)))
struct reap
{
struct lsh_object header;
void (*reap)(struct reap *closure, pid_t pid, struct exit_callback *callback);
};
#define REAP(r, p, c) ((r)->reap((r), (p), (c)))
struct reaper *make_reaper(void);
void reaper_run(struct reaper *r, struct io_backend *b);
#endif /* LSH_REAPER_H_INCLUDED */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment