[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Problems with the undead (zombies)



Brandon Mitchell <bhmit1@mail.wm.edu> writes:

> Placing a wait someone else may cause your program to hang until a child
> dies.  But note that if you have a select or some other kernel call, you
> will exit from that call with some kind of error code (it took me a while
> to realize this, never stopped using perror since then).

This depends on how you compile your code (i.e. if _BSD_SOURCE gets
defined, then the calls don't get interrupted.)  You can also set it
with siginterrupt(); or just use the POSIX sigaction() function, which
is always the best way.

Of course, perror() is still a good idea.


Jason Gunthorpe <jgg@gpu.srv.ualberta.ca> writes:

> The man pages do not say that wait is signal safe, putting it in a single
> handler could nuke your program in some situations.

The libc info pages definitely show waitpid() as part of a signal
handler.  It should be safe as long as you don't call it anywhere else 
where the SIGCHLD could interrupt it.


Gergely Madarasz <gorgo@caesar.elte.hu> writes:

> Hmm... isn't signal(SIGCHLD,SIG_IGN) the best for this situation anyway?

It is on Linux, with libc5 and libc6.

Fun with signals: fork a process (like `sleep 60') then exec() another
program, which gets the SIGCHLD signal when your process ends.  A few
programs take this quite badly.


Anyway, I think the program below is a good demo of how signals can be
safely handled.  If you pass it any arguments, it passes SA_RESTART to
sigaction().  (If you feel you need to reply to this, please don't
quote the whole program.)

-----
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

static volatile int status;
static volatile pid_t pid;
static volatile int done = 0;

void sig_chld(int num)
{
	int this_sts;
	pid_t this_pid;

	if (num != SIGCHLD) return;

	while (1) {
		if ((this_pid = waitpid(WAIT_ANY, &this_sts, WNOHANG)) > 0) {
			if (this_pid == pid) {
				status = this_sts;
				done = 1;
			}
		}
		else break;
	}
}

int main(int argc, char **argv)
{
	ssize_t n;
	char buf[1024];
	struct sigaction sa;

	pid = fork();

	if (pid == 0) {
		sleep(3);
		_exit(EXIT_SUCCESS);
	} else if (pid < 0) {
		perror("fork");
		exit(EXIT_FAILURE);
	}

	sa.sa_handler = sig_chld;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_NOCLDSTOP;
	if (argc > 1)
		sa.sa_flags |= SA_RESTART;

	if (sigaction(SIGCHLD, &sa, NULL) == -1) {
		perror("sigaction");
		exit(EXIT_FAILURE);
	}

	if ((n = read(0, buf, 1024)) == -1)
		perror("read");
	else
		printf("read got %d bytes\n", n);

	if (done)
		printf("child exited with status 0x%04x\n", status);

	return 0;
}
-----

-- 
	 Carey Evans  http://home.clear.net.nz/pages/c.evans/

"[UNIX] appears to have the inside track on being the replacement for
  CP/M on the largest microcomputers (e.g. those based on 68000...)"


--
To UNSUBSCRIBE, email to debian-devel-request@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org


Reply to: