From owner-freebsd-hackers@FreeBSD.ORG Wed Feb 10 17:25:28 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 B67E010656C2 for ; Wed, 10 Feb 2010 17:25:28 +0000 (UTC) (envelope-from gujjenaveen@gmail.com) Received: from mail-pz0-f202.google.com (mail-pz0-f202.google.com [209.85.222.202]) by mx1.freebsd.org (Postfix) with ESMTP id 8E1A08FC0C for ; Wed, 10 Feb 2010 17:25:28 +0000 (UTC) Received: by pzk40 with SMTP id 40so238930pzk.7 for ; Wed, 10 Feb 2010 09:25:28 -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=el6A3eG0R+XGirSPbDYV9pfy37jgG5MKI7bk3Sn9UfE=; b=eSu25133cmkIlRf1Zx9jqbBPl1VVTjHNvaXLJCzSZ8uFkIwjQXm70MXpuiP2o/bb2q iyPskd75+zkx6p4ieCqTBoq2h4IJAy6G72c8pfkc4/G169UU3QAkwV/EHMhVWi4DwC3l tLnqihPLhtkpmz94sl08VVvmUiNFh9ILnVCDo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:date:message-id:subject:from:to:content-type; b=bdYeTvS4wmnV1dO+ecY8XuVYO1xk/elIIbnrOt6HUsbu01dyFCPSYXjHC7VihwSLZf cbTyppn5H/YmyiCu548aMDbf64RTXNdQTUbL5/9OzDe9umq4lUp+q/w6kAMpQYC7KAeV W24qJAfvEB1wf1e9pBGNkan1YiTA4VRtKS5js= MIME-Version: 1.0 Received: by 10.141.106.6 with SMTP id i6mr350394rvm.11.1265822728008; Wed, 10 Feb 2010 09:25:28 -0800 (PST) Date: Wed, 10 Feb 2010 22:55:27 +0530 Message-ID: <39c945731002100925i2e466768peac89cdef15463f2@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: Re: 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 17:25:28 -0000 Naveen Gujje > wrote: >> 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); >> } >There are several problems with your signal handler. >First, the perror() and syslog() functions are not re-entrant, >so they should not be used inside signal handlers. This can >lead to undefined behaviour. Please refer to the sigaction(2) >manual page for a list of functions that are considered safe >to be used inside signal handlers. >Second, you are using functions that may change the value of >the global errno variable. Therefore you must save its value >at the beginning of the signal handler, and restore it at the >end. >Third (not a problem in this particular case, AFAICT, but >still good to know): Unlike SysV systems, BSD systems do >_not_ automatically reset the signal action when the handler >is called. Therefore you do not have to call signal() again >in the handler (but it shouldn't hurt either). Because of >the semantic difference of the signal() function on different >systems, it is preferable to use sigaction(2) instead in >portable code. Okay, I followed your suggestion and changed my SigChildHandler to void SigChildHandler(int sig) { pid_t pid; int status; int saved_errno = errno; while (((pid = waitpid( (pid_t) -1, &status, WNOHANG)) > 0) || ((-1 == pid) && (EINTR == errno))) ; errno = saved_errno; } and used sigaction(2) to register this handler. Still, system(3) returns -1 with errno set to ECHILD. >> 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. >I don't think that can happen. >> 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. >The system() function temporarily blocks SIGCHLD (i.e. it >adds the signal to the process' signal mask). However, >blocking is different from ignoring: The signal is held >as long as it is blocked, and as soon as it is removed >from the mask, it is delivered, i.e. your signal handler >is called right before the system() function returns. Yes, I agree with you. Here, I believe, the point in blocking SIGCHLD is to give preference to wait4() of system() over any other waitXXX() in parent process. But I still cant get the reason for wait4() to return -1. >And since you don't save the errno value, your signal >handler overwrites the value returned from the system() >function. So you get ECHILD. I had a debug print just after wait4() in system() and before we unblock SIGCHLD. And it's clear that wait4() is returning -1 with errno as ECHILD. >Best regards > Oliver --