从C++应用程序启动Linux服务时避免套接字继承

jga*_*ida 5 c++ sockets linux boost boost-asio

我有一个Linux服务(守护进程),它有多个线程,并使用boost io_service监听TCP套接字.当我在该套接字上收到某个消息时,我想用例如启动另一个服务/etc/init.d/corosync start.

问题是,在启动服务后,当我退出自己的服务时,另一个服务从我自己的服务继承了套接字,并且它仍处于一种奇怪的状态,我无法以通常的方式停止它.

在退出我的进程"MonitorSipServer"之前,打开的套接字显示如下:

netstat -anop |grep 144
tcp        0      0 0.0.0.0:20144           0.0.0.0:*               LISTEN          4480/MonitorSipServ off (0.00/0/0)
tcp        0      0 140.0.24.181:20144      140.0.101.75:47036      ESTABLISHED 4480/MonitorSipServ off (0.00/0/0)
Run Code Online (Sandbox Code Playgroud)

退出我的进程"MonitorSipServer"后,打开的套接字显示如下:

netstat -anop |grep 144
tcp        0      0 0.0.0.0:20144           0.0.0.0:*               LISTEN      4502/corosync    off (0.00/0/0)
tcp        0      0 140.0.24.181:20144      140.0.101.75:47036      ESTABLISHED 4502/corosync    off (0.00/0/0)
Run Code Online (Sandbox Code Playgroud)

我已经试过system,popen并与fork+ execvexecvenull环境.它总是相同或更糟.我最后的希望是Linux setsid命令,但它也没有用.

任何帮助,将不胜感激.此致,Jan

Ulf*_*zer 5

如果你指的是套接字描述符本身被exec'd子进程继承,并且这是不可取的,那么你可以SOCK_CLOEXEC在创建套接字时通过socket(2),以确保在执行其他程序时它们被关闭.(顺便说一下,这不会关闭连接,因为你的程序仍然有对套接字的引用.)

如果您正在使用某个更高级别的库,那么检查是否有某种方法可以让它传递此标志,或者fcntl(sock_fd, F_SETFD, fcntl(sock_fd, F_GETFD) | FD_CLOEXEC)如果您可以访问它,则在创建它之后在描述符上设置close-on-exec标志.(但是fcntl(2)在多线程环境中,这种方法可能很活泼,因为某些线程可以exec(3)在创建套接字的时间点和FD_CLOEXEC设置套接字的时间点之间进行编程.)

如果以上操作不起作用,那么您可以在执行服务之前手动fork(2)然后再close(2)使用套接字描述符.优点SOCK_CLOEXEC是套接字只有在exec*()实际成功时才会关闭,这有时可以更容易地从错误中恢复.此外,SOCK_CLOEXEC可以避免一些比赛,并使忘记关闭描述符更加困难.

  • 另请注意,在许多情况下,您无法控制所有文件描述符以及它们是否使用SOCK_CLOEXEC创建,在这种情况下,您可以运行一个循环,在fork()之后关闭()所有描述符,直到sysconf(_SC_OPEN_MAX) (如果你想单独留下stdin/out/err,或者将它们重定向到/ dev/null,可能从fd 3开始) (2认同)