NetBSD-Users archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
signal handling problem
Hi,
can anyone tell me whats wrong with the following code fragment?
I've trimmed out the guts of the code and just left the signal and process
setup and handling (If you want to see the whole thing its cnid_metad.c
from the netatalk 2.1.2 release).
As written it fails to reap children (on 5.1_RC3) but if you remove the
"if (sigchild)" prior to the "while ((pid = waitpid..." it works.
cheers
mark
static volatile sig_atomic_t sigchild = 0;
struct server {
char *name;
pid_t pid;
int control_fd; /* file descriptor to child cnid_dbd
process */
};
static struct server srv[MAXVOLS];
/* -------------------- */
static int maybe_start_dbd(char *dbdpn, char *dbdir, char *usockfn)
{
pid_t pid;
struct server *up;
up = test_usockfn(dbdir);
if (up && up->pid) {
/* we already have a process, send our fd */
if (send_cred(up->control_fd, rqstfd) < 0) {
/* FIXME */
return -1;
}
return 0;
}
if ((pid = fork()) < 0) {
return -1;
}
if (pid == 0) {
ret = execlp(dbdpn, dbdpn, dbdir, buf1, buf2, logconfig, NULL);
exit(0);
}
/*
* Parent.
*/
up->pid = pid;
return 0;
}
/* ------------------ */
static void catch_child(int sig _U_)
{
sigchild = 1;
}
/* ----------------------- */
static void set_signal(void)
{
struct sigaction sv;
sigset_t set;
signal(SIGPIPE, SIG_IGN);
sv.sa_handler = catch_child;
sv.sa_flags = SA_NOCLDSTOP;
sigemptyset(&sv.sa_mask);
if (sigaction(SIGCHLD, &sv, NULL) < 0) {
LOG(log_error, logtype_cnid, "cnid_metad: sigaction: %s",
strerror(errno));
exit(1);
}
/* block everywhere but in pselect */
sigemptyset(&set);
sigaddset(&set, SIGCHLD);
sigprocmask(SIG_BLOCK, &set, NULL);
}
int usockfd_check(int sockfd, const sigset_t *sigset)
{
int fd;
socklen_t size;
fd_set readfds;
int ret;
struct timeval tv;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
if ((ret = pselect(sockfd + 1, &readfds, NULL, NULL, NULL, sigset)) <
0) {
if (errno == EINTR)
return 0;
return -1;
}
}
/* ------------------ */
int main(int argc, char *argv[])
{
pid_t pid;
int status;
int ret;
sigset_t set;
set_signal();
sigemptyset(&set);
sigprocmask(SIG_SETMASK, NULL, &set);
sigdelset(&set, SIGCHLD);
while (1) {
rqstfd = usockfd_check(srvfd, &set);
/* Collect zombie processes and log what happened to them */
if (sigchild) while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
for (i = 0; i < MAXVOLS; i++) {
if (srv[i].pid == pid) {
srv[i].pid = 0;
break;
}
}
if (WIFEXITED(status)) {
LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with
exit code %i",
pid, WEXITSTATUS(status));
}
else if (WIFSIGNALED(status)) {
LOG(log_info, logtype_cnid, "cnid_dbd pid %i exited with
signal %i",
pid, WTERMSIG(status));
}
sigchild = 0;
}
if (rqstfd <= 0)
continue;
maybe_start_dbd(dbdpn, dbdir, dbp->usock_file);
}
}
Home |
Main Index |
Thread Index |
Old Index