From owner-freebsd-hackers@FreeBSD.ORG Wed Feb 10 07:40:05 2010 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 427FB106566B for ; Wed, 10 Feb 2010 07:40:05 +0000 (UTC) (envelope-from gujjenaveen@gmail.com) Received: from mail-px0-f203.google.com (mail-px0-f203.google.com [209.85.216.203]) by mx1.freebsd.org (Postfix) with ESMTP id 18AC38FC1A for ; Wed, 10 Feb 2010 07:40:04 +0000 (UTC) Received: by pxi41 with SMTP id 41so8403124pxi.27 for ; Tue, 09 Feb 2010 23:40:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:date:message-id:subject :from:to:content-type; bh=u013c/zeNRHM+sTMueAzZzh1fc0K3sNO+wo3RKwV4mE=; b=oTmy0tF9KB6/XPCOux3kCErxGPHWvivvuSkzSq+7ipYbkuFvZ+83si2JYeNrLBSwG0 5UTAEDMT/TVodqfeMi1nyhyzT6za4hRcrtWKdFbRjFRFnRiFjFn07ZJ35apj9hPonsCj MWb3jBh6kYpXNC/YVS2HATooQ2pPHLNvevmK4= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=FqiS6UvI1XDJkojbWkn33cgYXW4m8/fc4uUzbFITJQ9U8729fZPk7/M80G8ZKy9Y61 hQfK5/p43zuoyFdSsk9CVOT7U5Pjplnp9XO65tHOPhWAUtDrLYBZmzrexcA9a23v2c3R oB686NGN9RjWwau/83CsAw9i0ceOAHv/LClPc= MIME-Version: 1.0 Received: by 10.141.89.2 with SMTP id r2mr6340088rvl.277.1265786097979; Tue, 09 Feb 2010 23:14:57 -0800 (PST) Date: Wed, 10 Feb 2010 12:44:57 +0530 Message-ID: <39c945731002092314u4a8fd100q69c0735a11e9063a@mail.gmail.com> From: Naveen Gujje To: freebsd-hackers@freebsd.org Content-Type: text/plain; charset=ISO-8859-1 X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: System() returning ECHILD error on FreeBSD 7.2 X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Feb 2010 07:40:05 -0000 Hi, We have a web proxy (running on FreeBSD 7.2-RELEASE-p2), where we register the SIGCHLD handler as follows: signal(SIGCHLD, SigChildHandler); void SigChildHandler(int sig) { pid_t pid; /* get status of all dead procs */ do { int procstat; pid = waitpid(-1, &procstat, WNOHANG); if (pid < 0) { if (errno == EINTR) continue; /* ignore it */ else { if (errno != ECHILD) perror("getting waitpid"); pid = 0; /* break out */ } } else if (pid != 0) syslog(LOG_INFO, "child process %d completed", (int) pid); } while (pid); signal(SIGCHLD, SigChildHandler); } And, in some other part of the code, we call system() to add an ethernet interface. This system() call is returning -1 with errno set to ECHILD, though the passed command is executed successfully. I have noticed that, the problem is observed only after we register SigChildHandler. If I have a simple statement like system("ls") before and after the call to signal(SIGCHLD, SigChildHandler), the call before setting signal handler succeeds without errors and the call after setting signal handler returns -1 with errno set to ECHILD. Here, I believe that within the system() call, the child exited before the parent got a chance to call _wait4 and thus resulted in ECHILD error. But, for the child to exit without notifying the parent, SIGCHLD has to be set to SIG_IGN in the parent and this is not the case, because we are already setting it to SigChildHandler. If I set SIGCHLD to SIG_DFL before calling system() then i don't see this problem. I would like to know how setting SIGCHLD to SIG_DFL or SigChildHanlder is making the difference. Can someone please help me out? [Note: Replacing signal() with sigaction() doesn't help either.] Following is the code for system() call cat /usr/src/lib/libc/stdlib/system.c int __system(command) const char *command; { pid_t pid, savedpid; int pstat; struct sigaction ign, intact, quitact; sigset_t newsigblock, oldsigblock; if (!command) /* just checking... */ return(1); /* * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save * existing signal dispositions. */ ign.sa_handler = SIG_IGN; (void)sigemptyset(&ign.sa_mask); ign.sa_flags = 0; (void)_sigaction(SIGINT, &ign, &intact); (void)_sigaction(SIGQUIT, &ign, &quitact); (void)sigemptyset(&newsigblock); (void)sigaddset(&newsigblock, SIGCHLD); (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock); switch(pid = fork()) { case -1: /* error */ break; case 0: /* child */ /* * Restore original signal dispositions and exec the command. */ (void)_sigaction(SIGINT, &intact, NULL); (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL); _exit(127); default: /* parent */ savedpid = pid; do { pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0); } while (pid == -1 && errno == EINTR); break; } (void)_sigaction(SIGINT, &intact, NULL); (void)_sigaction(SIGQUIT, &quitact, NULL); (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL); return(pid == -1 ? -1 : pstat); } Thanks, Naveen