php - Difference between return value of non-blocking flock function and the $wouldblock argument? -
i'm trying understand non blocking flock , wouldblock argument
$fp = fopen('/tmp/lock.txt', 'r+'); if(flock($fp, lock_ex | lock_nb, $wouldblock)) { echo 'lock obtained'; } else{ echo 'unable obtain lock'; } fclose($fp);
documentation says wouldblock:
the optional third argument set 1 if lock block (ewouldblock errno condition).
reproducing in test enviroment concurrent condition, if process has gained lock, flock function immeditatly return false (non blocking)
so why should care $wouldblock value if return value of flock function in non-blocking mode allready tells me lock couldn't obtained?
i can't difference between flock function returning false , $wouldblock argument setted 1, , $wouldblock argument usefull for.
this because flock()
may fail not because lock gained somewhere else. in such case wouldn't block waiting lock being released, return false. in other words lock_nb
if flock returns false , wouldblock=1 means, tried gain lock acquired somewhere else. if flock lock_nb
returns false , wouldblock=0 means bad happen , flock didn't consider waiting gain lock impossible.
check out code(here gist):
<?php // let's create /tmp/ninja-lock1.txt ... $fp0 = fopen('/tmp/ninja-lock1.txt', 'c'); // ... , close imiedietly fclose($fp0); // file handler $fp0 closed flock() // unable use gain lock. // fail wouldblock set 0 // doesn't make sense wait on unusable file handle. // // btw flock() throws in such case warning "x not valid stream resource". // purpose of clear output example // i've suppressed @ - don't use @ in production $flockresult = @flock($fp0, lock_ex | lock_nb, $wouldblock); printf("flock=%b; wouldblock=%d (acquire lock: %s)\n", $flockresult, $wouldblock, "failure, broken file handle"); // 2 handlers /tmp/ninja-lock2.txt // show flock() blocking result. $fp1 = fopen('/tmp/ninja-lock2.txt', 'c'); $fp2 = fopen('/tmp/ninja-lock2.txt', 'c'); // nobody locking on /tmp/ninja-lock2.txt, // acquire lock , wouldblock 0 $flockresult = flock($fp1, lock_ex | lock_nb, $wouldblock); printf("flock=%b; wouldblock=%d (acquire lock: %s)\n", $flockresult, $wouldblock, "success"); // file locked on $fp1 handle flock won't acquire lock // , wouldblock 1 $flockresult = flock($fp2, lock_ex | lock_nb, $wouldblock); printf("flock=%b; wouldblock=%d (acquire lock: %s)\n", $flockresult, $wouldblock, "failure, acquired somewhere else"); // result: // $ php flock.php // flock=0; wouldblock=0 (acquire lock: failure, broken file handle) // flock=1; wouldblock=0 (acquire lock: success) // flock=0; wouldblock=1 (acquire lock: failure, acquired somewhere else) ?>
also clear confusion of future readers it's worth note checking ewouldblock
makes sense flock() lock_nb
flag, in blocking mode it's either success , block or failure , no block.
you can confirm looking php source code flock:
phpapi int php_flock(int fd, int operation) #if have_struct_flock /* {{{ */ { struct flock flck; int ret; flck.l_start = flck.l_len = 0; flck.l_whence = seek_set; if (operation & lock_sh) flck.l_type = f_rdlck; else if (operation & lock_ex) flck.l_type = f_wrlck; else if (operation & lock_un) flck.l_type = f_unlck; else { errno = einval; return -1; } ret = fcntl(fd, operation & lock_nb ? f_setlk : f_setlkw, &flck); if (operation & lock_nb && ret == -1 && (errno == eacces || errno == eagain)) errno = ewouldblock; if (ret != -1) ret = 0; return ret; }
ewouldblock
set if operation & lock_nb && ret == -1 && (errno == eacces || errno == eagain)
.
if more interested in implementation can read man page of fcntl, parts f_setlk
, f_setlkw
:
f_setlk
acquire lock (when l_type f_rdlck or f_wrlck) or release lock (when l_type f_unlck) on bytes specified l_whence, l_start, , l_len fields of lock. if conflicting lock held process, call returns -1 , sets errno eacces or eagain.
f_setlkw
as f_setlk, if conflicting lock held on file, wait lock released. if signal caught while waiting, call interrupted , (after signal handler has returned) returns (with return value -1 , errno set eintr).
Comments
Post a Comment