From patchwork Sun May 6 16:40:34 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Herbert Xu X-Patchwork-Id: 10382895 X-Patchwork-Delegate: herbert@gondor.apana.org.au Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E4F9560353 for ; Sun, 6 May 2018 16:40:42 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C43D328B26 for ; Sun, 6 May 2018 16:40:42 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B8ABA28B5D; Sun, 6 May 2018 16:40:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-7.9 required=2.0 tests=BAYES_00, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 150E628B54 for ; Sun, 6 May 2018 16:40:41 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751774AbeEFQkl (ORCPT ); Sun, 6 May 2018 12:40:41 -0400 Received: from orcrist.hmeau.com ([104.223.48.154]:36478 "EHLO deadmen.hmeau.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751711AbeEFQkk (ORCPT ); Sun, 6 May 2018 12:40:40 -0400 Received: from gondobar.mordor.me.apana.org.au ([192.168.128.4] helo=gondobar) by deadmen.hmeau.com with esmtps (Exim 4.89 #2 (Debian)) id 1fFMiB-0008R5-MW; Mon, 07 May 2018 00:40:35 +0800 Received: from herbert by gondobar with local (Exim 4.89) (envelope-from ) id 1fFMiA-0007B2-FK; Mon, 07 May 2018 00:40:34 +0800 Date: Mon, 7 May 2018 00:40:34 +0800 From: Herbert Xu To: Jilles Tjoelker Cc: Leah Neukirchen , dash@vger.kernel.org Subject: [PATCH v3] jobs - Do not block when waiting on SIGCHLD Message-ID: <20180506164034.s6y4n7yt2gianh63@gondor.apana.org.au> References: <87wowjsfcw.fsf@gmail.com> <20180505160243.t5rujv3eifiust5a@gondor.apana.org.au> <20180506135343.GB39956@stack.nl> <20180506162449.u6ld2meqmmxwdmgc@gondor.apana.org.au> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20180506162449.u6ld2meqmmxwdmgc@gondor.apana.org.au> User-Agent: NeoMutt/20170113 (1.7.2) Sender: dash-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dash@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Mon, May 07, 2018 at 12:24:49AM +0800, Herbert Xu wrote: > > However, a bigger issue is that the original fix was incomplete. > In particular, multiple jobs may have exited when gotsigchld is > set. But the loop will exit after just waiting for one job if > no new jobs exit triggering a new SIGCHLD. In fact there is another regression with the original patch: foreground jobs may trigger a showjob() if interrupted by SIGINT. So here is a new version. ---8<--- Because of the nature of SIGCHLD, the process may have already been waited on and therefore we must be prepared for the case that wait may block. So ensure that it doesn't by using WNOHANG. Furthermore, multiple jobs may have exited when gotsigchld is set. Therefore we need to wait until there are no zombies left. Lastly, waitforjob needs to be called with interrupts off and the original patch broke that. Fixes: 03876c0743a5 ("eval: Reap zombies after built-in...") Signed-off-by: Herbert Xu diff --git a/src/eval.c b/src/eval.c index a27d657..39c4e41 100644 --- a/src/eval.c +++ b/src/eval.c @@ -859,10 +859,8 @@ bail: if (!(flags & EV_EXIT) || have_traps()) { INTOFF; jp = makejob(cmd, 1); - if (forkshell(jp, cmd, FORK_FG) != 0) { - INTON; + if (forkshell(jp, cmd, FORK_FG) != 0) break; - } FORCEINTON; } listsetvar(varlist.list, VEXPORT|VSTACK); @@ -875,11 +873,8 @@ bail: if (execcmd && argc > 1) listsetvar(varlist.list, VEXPORT); } - if (evalbltin(cmdentry.u.cmd, argc, argv, flags)) { - if (exception == EXERROR && spclbltin <= 0) { - FORCEINTON; - break; - } + if (evalbltin(cmdentry.u.cmd, argc, argv, flags) && + !(exception == EXERROR && spclbltin <= 0)) { raise: longjmp(handler->loc, 1); } @@ -892,6 +887,7 @@ raise: } status = waitforjob(jp); + FORCEINTON; out: if (cmd->ncmd.redirect) diff --git a/src/jobs.c b/src/jobs.c index 1a97c54..606d603 100644 --- a/src/jobs.c +++ b/src/jobs.c @@ -975,10 +975,17 @@ waitforjob(struct job *jp) int st; TRACE(("waitforjob(%%%d) called\n", jp ? jobno(jp) : 0)); - while ((jp && jp->state == JOBRUNNING) || gotsigchld) - dowait(DOWAIT_BLOCK, jp); - if (!jp) + if (!jp) { + int pid = gotsigchld; + + while (pid > 0) + pid = dowait(DOWAIT_NORMAL, NULL); + return exitstatus; + } + + while (jp->state == JOBRUNNING) + dowait(DOWAIT_BLOCK, jp); st = getstatus(jp); #if JOBS if (jp->jobctl) {