aby*_*s.7 6 c sockets macos exec fcntl
当我在 Linux 上创建套接字时,可以O_CLOEXEC
在创建时指定标志:
auto fd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0);
Run Code Online (Sandbox Code Playgroud)
所以没有办法,其他线程会在这个套接字保持打开的情况下做fork()
+ exec()
。
但是在 Mac 上,根据手册,我不能做同样的事情:
套接字具有指定的类型,它指定了通信的语义。当前定义的类型有: SOCK_STREAM SOCK_DGRAM SOCK_RAW SOCK_SEQPACKET SOCK_RDM
该标志O_CLOEXEC
只能通过调用来设置fcntl()
。而且这不是原子方式 - 某些线程可能会exec()
在对socket()
和 的调用之间执行fcntl()
。
如何解决这个问题?
假设您的代码使用 pthreads,请考虑使用“pthread_atfork”,这使得可以为分叉指定回调。扩展了 Alk 帖子的想法,但在 fork 回调中实现了等待。
从OP来看,看起来可以控制创建套接字的代码(在Linux中它将使用SOCK_CLOEXEC),但不可能控制或修改分叉调用。
mutex_t socket_lock ;
main()
{
...
// establish atfork, before starting any thread.
mutex_t socket_lock = mutex_init(...);
pthread_atfork(set_socket_lock, release_sock_lock, release_sock_lock) ;
pthread_create(...) ;
.. rest of the code ...
}
int socket_wrapper(...)
{
set_socket_lock() ;
int sd = socket(..);
fcntl(sd, O_CLOEXEC);
release_socket_lock();
return sd;
}
void set_socket_lock(void)
{
lock(socket_lock ) ;
}
void release_socket_lock(void)
unlock(socket_lock ) ;
}
Run Code Online (Sandbox Code Playgroud)
作为额外的好处,上述逻辑互斥体还将涵盖调用 fork 的情况,并且在执行 fork 时,父/子线程中的一个线程将尝试创建套接字。不确定这是否可能,因为内核可能在开始任何分叉活动之前首先挂起所有线程。
免责声明:我没有尝试运行代码,因为我无法访问 Mac 计算机。