bash dropping SIGHUPs

I've written a daemon in bash, that waits for a HUP signal and then does some processing, before waiting for the next HUP. It goes something like this:

trap gothup=1 HUP
while :; do
    gothup=0

    # do some processing ...

    # now wait for a HUP ...
    while [ $gothup -eq 0 ]; do
        sleep 30 &
        wpid=$!

        if [ $gothup -eq 0 ]; then
            wait $wpid
            [ $? -lt 128 ] && continue
        fi

        # kill $wpid if still running ...

    done
done

I couldn't figure out a way to get bash to store up signals during a critical piece of code. The above was the best I could get, but my concern is, what if I receive a HUP *after* this test:

        if [ $gothup -eq 0 ]; then

but before the next instruction:

            wait $wpid

In that scenario, the wait will block for 30 seconds or until another HUP is received, i.e. it would have missed one HUP.

How can I improve this so there's no chance of missing a HUP?

Thanks,
Mark.

I don't think it's ever going to miss a HUP, it will still set the variable. The loop may just detect it 30 seconds late.

There's no point backgrounding sleep 30 when all you're going to do is wait for it. You catch the circumstance when HUP comes in the instant between running wait and waiting for wait, and open 3 other circumstances where the HUP could creep in before you're ready.

A C application would use SIGMASK to temporarily stop a signal but shell doesn't have this... hmm...

How about a pipe?

#!/bin/sh

trap "rm -f /tmp/$$" HUP

echo "pid is $$"
exec 5>&2               # Save stderr
exec  2> /dev/null      # stop error spew

while true
do
        mkfifo /tmp/$$  # Recreate FIFO

        # wait for fifo to be deleted, which will make read fail
        while read X < /tmp/$$ ; do true ; done

        echo "read loop broken"
done

exec 2>&5       # restore stderr
exec 5>&-       # close fd 5

The shell will create a FIFO and try to read from it. Since there's no other process writing to it, it will block until something does something to it. A HUP signal will delete the FIFO, causing the read to fail. Once it's ready, the shell will create a new FIFO and start over.

Redirecting stderr is necessary since deleting the FIFO causes a bit of error spam. You can redirect into >&5 if you need to write to stderr.

Tested this in lots of shells and two OSes so it looks decently portable.

The trouble with using a FIFO is that's not going to support multiple clients attempting to contact the daemon simultaneously ...

Maybe I've just reached the limit of what is achievable in bash.:wall:

Well, you can't do that with posix signals in any environment. If multiple clients signal the daemon simultaneously, using the same signal number, it's possible that the daemon will only receive that signal once. While if instead the daemon reads a fifo, multiple clients can write to it without having their messages lost. And, so long as the messages are smaller than or equal to PIPE_BUF bytes, multiple clients writing to the same fifo will each have their messages written atomically, without interleaving.

Regards,
Alister

That's not exactly what I'm doing there, I'm just using it as an ad-hoc semaphore. :o But yes, asking why he's using signals for this is a good idea.