关于 pthread_create 和文件描述符,我可以假设什么?
What can I assume about pthread_create and file descriptors?
我刚调试了一个程序,大致做了:
pthread_create(...);
close(0);
int t = open("/named_pipe");
assert(t == 0);
偶尔会失败,因为 pthread_create
实际上会在新线程上短暂地打开文件描述符——特别是 /sys/devices/system/cpu/online
——如果你运气不好,它会发生在 close
和 [=15 之间=] 以上,使 t
不是 0.
最安全的方法是什么?如果关于文件描述符的 pthread_create
有任何保证怎么办?我能保证如果在我调用 pthread_create 之前打开了 3 个文件描述符,那么当它返回并且控制权已传递到新线程上的我的函数时也会有 3 个打开吗?
在多线程程序中,需要使用dup2
or dup3
来替换文件描述符。在 close
之后立即重用的旧技巧不再有效,因为其他线程随时创建文件描述符。此类文件描述符甚至可以由 glibc 隐式创建(和关闭),因为许多内核接口都使用文件描述符。
dup2
是标准接口。 Linux 也有 dup3
,您可以使用它自动创建带有 O_CLOEXEC
标志集的文件描述符。否则,仍然会存在竞争条件,如果进程分叉并执行新程序,描述符可能会泄漏到子进程。
我刚调试了一个程序,大致做了:
pthread_create(...);
close(0);
int t = open("/named_pipe");
assert(t == 0);
偶尔会失败,因为 pthread_create
实际上会在新线程上短暂地打开文件描述符——特别是 /sys/devices/system/cpu/online
——如果你运气不好,它会发生在 close
和 [=15 之间=] 以上,使 t
不是 0.
最安全的方法是什么?如果关于文件描述符的 pthread_create
有任何保证怎么办?我能保证如果在我调用 pthread_create 之前打开了 3 个文件描述符,那么当它返回并且控制权已传递到新线程上的我的函数时也会有 3 个打开吗?
在多线程程序中,需要使用dup2
or dup3
来替换文件描述符。在 close
之后立即重用的旧技巧不再有效,因为其他线程随时创建文件描述符。此类文件描述符甚至可以由 glibc 隐式创建(和关闭),因为许多内核接口都使用文件描述符。
dup2
是标准接口。 Linux 也有 dup3
,您可以使用它自动创建带有 O_CLOEXEC
标志集的文件描述符。否则,仍然会存在竞争条件,如果进程分叉并执行新程序,描述符可能会泄漏到子进程。