[Bugs] [Bug 1718562] flock failure (regression)

bugzilla at redhat.com bugzilla at redhat.com
Wed Jun 19 09:09:56 UTC 2019


https://bugzilla.redhat.com/show_bug.cgi?id=1718562



--- Comment #4 from Jaco Kroon <jaco at uls.co.za> ---
I've managed to implement a workaround for this in php/bash (C/C++ will be
similar).

This "work around" is perhaps how locking should have been implemented in the
first place on our end (lock files gets removed post use).

The code uses a small(ish 1s) timeout per flock() call due to the bug, a more
global timeout would be better but given the bug here doesn't work as well as
can be done.  Recursion can (and should) be eliminated but I haven't spent a
lot of time on this (getting it out the door was more urgent than making it
optimal).  This code does have the single advantage that lock files gets
removed post use again (it's based on discussions with other parties).

The other option for folks running into this is to look at dotlockfile(1) which
doesn't rely on flock() but has other major timing gap issues (retries are
atomic, but waiting is a simple sleep + retry, so if other processes grabs
locks at the wrong time the invoking process could starve/fail without the need
to do so).

Bash:

#! /bin/sh

function getlock()
{
        local fd="$1"
        local lockfile="$2"
        local waittime="$3"

        eval "exec $fd>\"\${lockfile}\"" || return $?
        local inum=$(stat -c%i - <&3)
        local lwait="-w1"
        [ "${waittime}" -le 0 ] && lwait=-n

        while ! flock -w1 -x 3; do
                if [ "$(stat -c%i "${lockfile}" 2>/dev/null)" != "${inum}" ];
then
                        eval "exec $fd>\"\${lockfile}\"" || return $?
                        local inum=$(stat -c%i - <&3)
                        continue
                fi
                (( waittime-- ))
                if [ $waittime -le 0 ]; then
                        eval "exec $fd<&-"
                        return 1
                fi
        done

        if [ "$(stat -c%i "${lockfile}" 2>/dev/null)" != "${inum}" ]; then
                eval "exec $fd<&-"
                getlock "$fd" "$lockfile" "${waittime}"
                return $?
        fi

        return 0
}

function releaselock()
{
        local fd="$1"
        local lockfile="$2"

        rm "${lockfile}"
        eval "exec $fd<&-"
}

PHP:

<?php
function getlock($filename, $lockwait = -1 /* seconds */)
{
        $lock = new stdClass;
        $lock->filename = $filename;
        $lock->fp = fopen($filename, "w");

        if (!$lock->fp)
                return NULL;

        $lstat = fstat($lock->fp);
        if (!$lstat) {
                fclose($lock->fp);
                return NULL;
        }

        pcntl_signal(SIGALRM, function() {}, false);

        pcntl_alarm(1);
        while (!flock($lock->fp, LOCK_EX)) {
                pcntl_alarm(0);
                clearstatcache(true, $filename);
                $nstat = stat($filename);
                if (!$nstat || $nstat['ino'] != $lstat['ino']) {
                        fclose($lock->fp);
                        $lock->fp = fopen($filename, "w");
                        if (!$lock->fp)
                                return NULL;

                        $lstat = fstat($lock->fp);
                        if (!$lstat) {
                                fclose($lock->fp);
                                return NULL;
                        }
                }

                if (--$lockwait < 0) {
                        fclose($lock->fp);
                        return NULL;
                }

                pcntl_alarm(1);
        }
        pcntl_alarm(0);

        clearstatcache(true, $filename);
        $nstat = stat($filename);
        if (!$nstat || $nstat['ino'] != $lstat['ino']) {
                fclose($lock->fp);
                return getlock($filename, $lockwait);
        }

        return $lock;
}

function releaselock($lock)
{
        unlink($lock->filename);
        fclose($lock->fp);
}
?>

-- 
You are receiving this mail because:
You are on the CC list for the bug.
You are the assignee for the bug.


More information about the Bugs mailing list