为什么这个用flock()获取的文件锁在调用exec()后没有释放?

Why is this file lock acquired with flock() not released after calling exec()?

我有这个 PHP 8.1 的最小示例:

<?php
ini_set('display_errors', 'on');
if(($fp = @fopen(__DIR__ . '/test.some', 'r+')) === false){
    $fp = fopen(__DIR__ . '/test.some', 'c+');
}
flock($fp, LOCK_EX);
exec('eval `ssh-agent -s`', $output1, $resultCode1);
var_dump($output1, $resultCode1);
fclose($fp);

问题是,当我 运行 这个脚本两次时,第二个实例将阻塞在 flock() 函数调用上,据说是因为第一个没有释放文件锁。

当我 exec() 一个不同的命令而不是 eval `ssh-agent -s`,例如 git --version,然后一切似乎工作正常。

有人知道问题出在哪里吗?是PHP的BUG还是我对flock()的理解太差?

通常,当进程退出时,所有文件锁都会自动释放 (source)。但是,ssh-agent 被派生为后台进程,这导致它从父进程继承所有文件锁。

此行为可以通过 运行 sudo fuser -v /tmp/test.some 确认,这表明 ssh-agent 继承了锁。

                     USER        PID ACCESS COMMAND
/tmp/test.some:      testuser    19834 F.... ssh-agent
                     testuser    19873 F.... php8.1

按照 Pran Joseph 评论中的建议添加 flock($fp, LOCK_UN),确实解决了这个问题。