5
\$\begingroup\$

This implementation is inspired by the POSIX functions sem_wait() and sem_post(). It tries to get rid of busy loops in the code and appears to work after some simple tests that have been done. But code involving concurrency is hard to get right. Hopefully, there are no race conditions and/or deadlocks in it.

Update 1

semInit() was changed a little bit since the last test. The change had a missing semicolon issue causing syntax error which I have just corrected in this update.

#!/bin/bash

##  Filename: semaphore.bash.inc

##  Blocking other processes by running the function as a
##  process to occupy flock semFile.
lkrRun()
{
    {
        flock -x 5
        while :; do
            sleep 30
        done
    } 5>/tmp/semFile
}

semInit()
{
    local semValArgInit="$1"
    { [ -z "$semValArgInit" ] || [ $semValArgInit -lt 0 ]; } && semValArgInit=0
    echo $semValArgInit >/tmp/semVal
    \rm -f /tmp/lkrPid
    touch /tmp/auxFile
    touch /tmp/semFile
}

semWait()
{
    local semValTmp
    while :; do
        flock -x 5
        [ $(cat /tmp/semVal) -eq 0 ] || {
            semValTmp=$(cat /tmp/semVal)
            let semValTmp--
            echo $semValTmp >/tmp/semVal
            flock -u 5
            break
        }
        { [ -f /tmp/lkrPid ] && kill -0 $(cat /tmp/lkrPid); } || {
            lkrRun &
            echo $! >/tmp/lkrPid
        }
        flock -u 5

        ##  Block point to prevent processes from busying at looping.
        ##  It should still work without it but just become
        ##  inefficient.
        flock -x 6

        flock -u 6
    done 5>/tmp/auxFile 6>/tmp/semFile
}

semPost()
{
    local semValTmp
    {
        flock -x 5
        semValTmp=$(cat /tmp/semVal)
        let semValTmp++
        echo $semValTmp >/tmp/semVal

        ##  Kill the whole locker's process group to relinquish
        ##  flock semFile and resume processes blocked on it.
        [ -f /tmp/lkrPid ] && kill -9 -- -$(cat /tmp/lkrPid)

        \rm -f /tmp/lkrPid
    } 5>/tmp/auxFile
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.