Skip to contentSkip to conversation

Hang opening a pipe written to by a child, with SIGCHLD

DISCUSSION Oleg Nesterov 1 participant 2 messages Apr 10, 2012 1 message not in the archive

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw
Quoted 32 lines · Andrew Morton

Begin forwarded message:

Date: Mon, 2 Apr 2012 16:46:11 +0200
From: Lluís Batlle i Rossell <[email protected]>
To: [email protected]
Subject: Hang opening a pipe written to by a child, with SIGCHLD

Hello,

I had troubles running a simple bash script where a child wrote to a named pipe before dying, and the parent opened and read the pipe.

On a computer, my script hangs always. Also under 'strace'. Not under 'strace -f'. Thinking of some race, I wrote a small script that hangs in the linuxes I could try (3.2.11 now):

----------
#!/var/run/current-system/sw/bin/bash

PIPE=/tmp/pipe

rm -f $PIPE
mkfifo $PIPE

function spawn {
echo DONE > $PIPE
}

spawn sleep 1 &

Quoted 7 lines

while true; do
echo reading
while read LINE < $PIPE; do
echo $LINE
spawn &
done
done

Looks like, it hangs "correctly". At least from the kernel pov.

The parent sleeps in fifo_open()->wait_for_partner(), but there are no pipe->writers.

Note that the parent (bash) re-opens /tmp/pipe after every "spawn". Now,

- the parent (bash) forks the new child

- the new child sleeps waiting for reader

- the parent does open(pipe), this wakes up the child

- the child opens the pipe, writes, and exits

- the open from the child wakes up the parent, but since it exits quickly fifo_open(FMODE_READ) can notice the pending SIGCHLD and return -EINTR

- the parent restarts sys_open(), but nobody can open it for writing

May be you can ask bash developers. Perhaps bash can move the "restore stdin" logic into the child process, I dunno.

Or may be you can "fix" this script, just add "exec < $PIPE" before the main "while true" loop.

Oleg.

#2 lore raw
Quoted 3 lines · Oleg Nesterov

Or may be you can "fix" this script, just add "exec < $PIPE" before the main "while true" loop.

Cough, no ;) this can equally race with the exiting child.

Oleg.