permisos open fputs español con php concurrency flock

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



open url php (1)

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 bloqueo bloquearía (condición EWOULDBLOCK errno).

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

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 bloqueo?

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 bloqueo ya se obtuvo en otro lugar. En tal caso, no bloquearía la espera de que se liberara el bloqueo, pero devolvería inmediatamente falso. En otras palabras, con LOCK_NB si flock devuelve false y willblock = 1, significa que intentó obtener el bloqueo 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 bloqueo ya que esto era completamente imposible.

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

<?php // Let''s create /tmp/ninja-lock1.txt ... $fp0 = fopen(''/tmp/ninja-lock1.txt'', ''c''); // ... and close it imiedietly fclose($fp0); // File handler $fp0 was closed so flock() // is unable to use it to gain lock. // It will fail with wouldblock set to 0 // as it doesn''t make sense to wait on unusable file handle. // // BTW flock() throws in such case warning "x is not a valid stream resource". // Just for the purpose of clear output from this example // I''ve suppressed it with @ - 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"); // Two handlers for /tmp/ninja-lock2.txt // to show flock() blocking result. $fp1 = fopen(''/tmp/ninja-lock2.txt'', ''c''); $fp2 = fopen(''/tmp/ninja-lock2.txt'', ''c''); // Nobody is locking on /tmp/ninja-lock2.txt, // so it will acquire lock and wouldblock will be 0 $flockResult = flock($fp1, LOCK_EX | LOCK_NB, $wouldblock); printf("flock=%b; wouldblock=%d (Acquire lock: %s)/n", $flockResult, $wouldblock, "success"); // File is locked on $fp1 handle so flock won''t acquire lock // and wouldblock will be 1 $flockResult = flock($fp2, LOCK_EX | LOCK_NB, $wouldblock); printf("flock=%b; wouldblock=%d (Acquire lock: %s)/n", $flockResult, $wouldblock, "failure, already 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, already acquired somewhere else) ?>

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 bloqueo es éxito y bloqueo 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 bloqueo (cuando l_type es F_RDLCK o F_WRLCK) o liberar un bloqueo (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 bloqueo 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 bloqueo conflictivo en el archivo, espere a que se libere ese bloqueo. 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).