我有一个多线程程序,其中带有 O_CREAT 的 sem_open 有时会因 EBADF 失败。这是在 NXP 的 ARM linux 4.9.88 嵌入式设备上。
重现起来非常困难,但我确实用 strace 发现了一种情况,在创建一个文件时,看起来两个线程正在接收相同的文件描述符(一个用于 sem_open 内的 openat(),另一个作为从 pipeline2 返回的读取端)文件和管道同时存在。
strace(pid 266是调用sem_open的线程,pid 268是另一个调用popen的线程)报告:
[pid 266] openat(AT_FDCWD, "/dev/shm/pPC113", O_RDWR|O_CREAT|O_EXCL, 0777 <unfinished ...>
[pid 268] close(12) = 0
[pid 268] mq_timedreceive(10, "\0\0\0\0\1g\7\0", 8, NULL, NULL) = 8
[pid 266] <... openat resumed> ) = 12
[pid 268] pipe2([12, 13], O_CLOEXEC) = 0
请注意,openat() 和 pipeline2() 都返回描述符 12,而它们本应返回不同的描述符。
随后,sem_open 尝试写入描述符 12,并接收 EBADF,大概是因为描述符 12 是管道的读取端而不是它创建的文件。
对我来说,这似乎是一个明显的内核错误; open 和 pipeline 都返回相同的文件描述符。有谁知道这是否是一个已知的错误,并在更高版本的内核中修复?