Это связано с тем, что flock()
может потерпеть неудачу не только потому, что замок уже получен где-то в другом месте. В таком случае он не блокирует ожидание блокировки, но сразу же возвращает false. Другими словами, с помощью LOCK_NB
, если flock возвращает false и willblock = 1, значит, он попытался получить блокировку, но он уже получен где-то в другом месте. Но если flock с LOCK_NB
возвращает false и beblock = 0, то это означает, что что-то действительно плохое происходит, и стая даже не рассматривала возможность ожидания блокировки, поскольку это было совершенно невозможно.
Проверьте этот код ( здесь также gist ):
Также, чтобы устранить любую путаницу будущих читателей, стоит отметить, что проверка EWOULDBLOCK
имеет смысл только для flock () с флагом LOCK_NB
, так как в режиме блокировки это либо успех, либо блок или сбой, и никакой блок.
Вы можете подтвердить это, посмотрев на php исходный код для 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
установлен только в том случае, если operation & LOCK_NB && ret == -1 &&
(errno == EACCES || errno == EAGAIN)
.
Если вас больше интересует реализация, вы также можете прочитать man fcntl , в основном части о F_SETLK
и F_SETLKW
:
F_SETLK
Получить блокировку (когда l_type - F_RDLCK или F_WRLCK) или освободить блокировку (когда l_type - F_UNLCK) в байтах, заданных полями l_whence, l_start и l_len блокировки. Если конфликтующая блокировка удерживается другим процессом, этот вызов возвращает -1 и устанавливает errno в EACCES или EAGAIN.
F_SETLKW
Что касается F_SETLK, но если конфликтующая блокировка сохраняется файл, затем дождитесь, когда этот замок будет выпущен. Если сигнал улавливается во время ожидания, то вызов прерывается и (после возврата обработчика сигнала) возвращается немедленно (с возвращаемым значением -1 и errno, установленным в EINTR).
blockquote>