From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.org/gmane.linux.lib.musl.general/12286 Path: news.gmane.org!.POSTED!not-for-mail From: Rich Felker Newsgroups: gmane.linux.lib.musl.general Subject: Re: Conformance problem in system() Date: Sat, 30 Dec 2017 17:22:04 -0500 Message-ID: <20171230222204.GF1627@brightrain.aerifal.cx> References: <20171229094848.lfunfbqvjc4gln5u@voyager> Reply-To: musl@lists.openwall.com NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Trace: blaine.gmane.org 1514672435 27523 195.159.176.226 (30 Dec 2017 22:20:35 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 30 Dec 2017 22:20:35 +0000 (UTC) User-Agent: Mutt/1.5.21 (2010-09-15) To: musl@lists.openwall.com Original-X-From: musl-return-12302-gllmg-musl=m.gmane.org@lists.openwall.com Sat Dec 30 23:20:31 2017 Return-path: Envelope-to: gllmg-musl@m.gmane.org Original-Received: from mother.openwall.net ([195.42.179.200]) by blaine.gmane.org with smtp (Exim 4.84_2) (envelope-from ) id 1eVPUL-0006ME-5F for gllmg-musl@m.gmane.org; Sat, 30 Dec 2017 23:20:21 +0100 Original-Received: (qmail 1324 invoked by uid 550); 30 Dec 2017 22:22:18 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Original-Received: (qmail 32741 invoked from network); 30 Dec 2017 22:22:17 -0000 Content-Disposition: inline In-Reply-To: <20171229094848.lfunfbqvjc4gln5u@voyager> Original-Sender: Rich Felker Xref: news.gmane.org gmane.linux.lib.musl.general:12286 Archived-At: On Fri, Dec 29, 2017 at 10:48:48AM +0100, Markus Wichmann wrote: > Hi all, > > I was testing system() while SIGCHLD is ignored just now, and noticed a > difference between glibc and musl. That in itself is not alarming, but > it prompted me to look this function up in the standard, to see which > behavior was conforming better (or maybe both are). > > The program was this: > > #include > #include > #include > > int main(void) > { > if (signal(SIGCHLD, SIG_IGN) == SIG_ERR) > perror("signal"); > int i = system("sleep 1"); > if (i != 0) > fprintf(stderr, "system() == %d, %m\n", i); > return i; > } > > Glibc returns -1 from system() while musl returns 32512. errno is the > same in both cases, ECHILD. Which is also what waitpid() is returning. > > SUSv4 specifies for system()'s return value: > > | [...][I]f the termination status for the command language interpreter > | cannot be obtained, system() shall return -1 and set errno to indicate > | the error. > > So, it turns out, glibc is conforming to the standard, and musl is not. > If waitpid() fails, then the status cannot be retrieved. > > I don't know about other system calls, but I tend to view pointer > arguments to system calls as undefined after a failed call. The kernel > might deposit something in those variables, or it might not. In this > case, it does not, so the status returned is the value status was > initialized to at the start of system(), which is 0x7f00, the value I > observed. I think you were hoping to land under the umbrella of > > | If command is not a null pointer, system() shall return the termination > | status of the command language interpreter in the format specified by > | waitpid(). > > But a failing waitpid() does not fetch the status at all. > > I have attached a patch to correct this behavior, for your perusal. I think you're right that there's a problem here, but I don't think the patch correctly or fully fixes it. A simpler version of what you're doing would be to just initialize status to -1 instead of 0x7f00, since your patch is returning -1 in all cases where waitpid did not complete successfully. But that ignores the POSIX requirement to behave as if the interpreter exited with status 127 when it was possibel to make the child process but the command interpreter could not be executed. musl's posix_spawn does not succeed when exec fails in the child; instead the exec error is returned. This behavior is permitted but not required by POSIX. I think it would actually be preferable to system to return -1 and set errno in this case too, but POSIX doesn't seem to allow that. So I think we actually need to break down error cases for posix_spawn and simulate the exit(127) result if the error returned is anything other than an error that could be returned by fork (EAGAIN or ENOMEM). Does that sound right? Rich