From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6904 invoked by alias); 6 Mar 2013 22:53:53 -0000 Mailing-List: contact zsh-workers-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Workers List List-Post: List-Help: X-Seq: 31119 Received: (qmail 13146 invoked from network); 6 Mar 2013 22:53:52 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.6 required=5.0 tests=BAYES_00,DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED,FREEMAIL_FROM,NML_ADSP_CUSTOM_MED,RCVD_IN_DNSWL_LOW, T_DKIM_INVALID,T_TO_NO_BRKTS_FREEMAIL autolearn=no version=3.3.2 Received-SPF: pass (ns1.primenet.com.au: SPF record at _netblocks.google.com designates 74.125.82.177 as permitted sender) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=x-received:date:from:to:subject:message-id:mail-followup-to :mime-version:content-type:content-disposition:user-agent; bh=WqL+pbquZB3Mg8oc6ojJWBBjjHAzj7sVC/7SVAcNo1o=; b=uATTgneG0snUg9mEkAcPtkDOIxnVk/sxCV/S7rgnqKbKZguI1AEF2vFHEwUfe0JfWR BVLKibKjigJzGLdLG6sgz7wfRj3KNw/9cwT8fJ4PrIsAgD2vG8hH1W45wS8/KgEZpR6x e/ZBf2Kp17cv2p0Rr+2qnCxoHuyEm5TvOWPfR2Qcwh/CciWueBbuV98a/hvXFYazhVHk 0gEZUsrscBkj2V/QACnCFpTrRaQ4+06IekUv9TLszn/VA0FRSOHUykNvG8W5v3I2N9AX FYSnR+kLZvhJUt1JwpvsQ9qlnMEovQzC56HWqCoqMOILxcENi2vskVyCoJS5xXruqRL+ yhhQ== X-Received: by 10.194.92.65 with SMTP id ck1mr32902731wjb.54.1362610423841; Wed, 06 Mar 2013 14:53:43 -0800 (PST) Date: Wed, 6 Mar 2013 22:53:41 +0000 From: Stephane Chazelas To: zsh-workers@zsh.org Subject: coproc fd leak leading to possible deadlock Message-ID: <20130306225341.GA12150@chaz.gmail.com> Mail-Followup-To: zsh-workers@zsh.org MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) When we run an external command as a coproc, all is fine, but if we run a subshell, that subshell ends up having open fds for both ends of both pipes, leading to potential deadlocks: ~$ exec zsh -f sc% coproc {sleep 100; sleep 100} [1] 14488 sc% ps -H PID TTY TIME CMD 14484 pts/6 00:00:00 zsh 14488 pts/6 00:00:00 zsh 14489 pts/6 00:00:00 sleep 14490 pts/6 00:00:00 ps sc% lsof -ad0-99 -p $! COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME zsh 14488 chazelas 0r FIFO 0,8 0t0 294217 pipe zsh 14488 chazelas 1w FIFO 0,8 0t0 294216 pipe zsh 14488 chazelas 2u CHR 136,6 0t0 9 /dev/pts/6 zsh 14488 chazelas 10u CHR 136,6 0t0 9 /dev/pts/6 zsh 14488 chazelas 11r FIFO 0,8 0t0 294216 pipe zsh 14488 chazelas 14w FIFO 0,8 0t0 294217 pipe Above, you see the lsof of the coproc. see how fd 11 is the reading end of the pipe on fd 1 and fd 14 is the writing end of the pipe on fd 0. For an external command, it's OK: sc% coproc sleep 20 [1] 14537 sc% lsof -ad0-99 -p $! COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME sleep 14537 chazelas 0r FIFO 0,8 0t0 293743 pipe sleep 14537 chazelas 1w FIFO 0,8 0t0 293742 pipe sleep 14537 chazelas 2u CHR 136,1 0t0 4 /dev/pts/1 A work around is to do: coproc sh -c 'sleep 100; exec sleep 100' Side question: is it possible to close any of the coproc pipes? >&p- or <&p- don't work. If I run another coproc, that closes the current one AFAICT, so I can do: coproc cmd exec {i}<&p {o}>&p coproc : exec {i}<&- as a work around, but I thought there should be a simpler way. Even when the coproc has terminated, the fds are not closed. sc% coproc sleep 10 [1] 14594 sc% lsof -ad11-20 -p $$ COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME zsh 12148 chazelas 11r FIFO 0,8 0t0 295967 pipe zsh 12148 chazelas 14w FIFO 0,8 0t0 295968 pipe sc% [1] + done sleep 10 sc% lsof -ad11-20 -p $$ COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME zsh 12148 chazelas 11r FIFO 0,8 0t0 295967 pipe zsh 12148 chazelas 14w FIFO 0,8 0t0 295968 pipe Having said that, zsh coproc is a lot more usable that bash's or ksh's. At least the issues can easily be worked around. -- Stephane