¿Diferencia entre el valor de retorno de la función de bandada no bloqueante y el argumento $ bloqueador?

Intento entender la bandada no bloqueadora y el argumento bloqueador

$fp = fopen('/tmp/lock.txt', 'r+'); if(flock($fp, LOCK_EX | LOCK_NB, $wouldblock)) { echo 'Lock obtained'; } else{ echo 'Unable to obtain lock'; } fclose($fp); 

La documentación dice sobre willblock:

El tercer argumento opcional se establece en 1 si el locking bloquearía (condición EWOULDBLOCK errno).

Reproduciendo en un entorno de prueba la condición concurrente, si otro proceso ha ganado locking, la función de grupo devuelve inmediatamente FALSE (no locking)

Entonces, ¿por qué debería preocuparme por $ willblock value si el valor de retorno de la función de flock en modo no bloqueado ya me dice que no se pudo obtener el locking?

No puedo hacer que la diferencia entre la función de bandada sea FALSE y el argumento $ blockbloqueado en 1, y para qué sirve el argumento $ blockblock.

Esto se debe a que flock() puede fallar no solo porque el locking ya se obtuvo en otro lugar. En tal caso, no bloquearía la espera de que se liberara el locking, pero devolvería inmediatamente falso. En otras palabras, con LOCK_NB si flock devuelve false y willblock = 1, significa que intentó obtener el locking pero que ya se adquirió en otro lugar. Pero si el grupo con LOCK_NB devuelve false y willblock = 0, significa que algo realmente malo sucedió y el rebaño ni siquiera consideró esperar para obtener el locking ya que esto era completamente imposible.

Mira este código ( aquí también hay una esencia ):

  

También para despejar cualquier confusión entre los futuros lectores, vale la pena observar que comprobar EWOULDBLOCK solo tiene sentido para flock () con el indicador LOCK_NB , ya que en el modo de locking es éxito y locking o falla y no hay bloque.

Puede confirmar esto mirando el código fuente php para bandada :

 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 se establece solo si la operation & LOCK_NB && ret == -1 && (errno == EACCES || errno == EAGAIN) .

Si está más interesado en la implementación, también puede leer la página man de fcntl , en su mayoría partes sobre F_SETLK y F_SETLKW :

F_SETLK

Adquirir un locking (cuando l_type es F_RDLCK o F_WRLCK) o liberar un locking (cuando l_type es F_UNLCK) en los bytes especificados por los campos l_whence, l_start y l_len de lock. Si otro proceso mantiene un locking en conflicto, esta llamada devuelve -1 y establece errno en EACCES o EAGAIN.

F_SETLKW

En cuanto a F_SETLK, pero si se mantiene un locking conflictivo en el archivo, espere a que se libere ese locking. Si se detecta una señal mientras se espera, la llamada se interrumpe y (después de que el manejador de señal haya regresado) regresa inmediatamente (con el valor de retorno -1 y errno establecido en EINTR).