简体   繁体   English

使用带有boost :: asio :: ip :: tcp :: iostream的fork()是否安全?

[英]Is it safe to use fork() with boost::asio::ip::tcp::iostream?

I'm attempting to daemonize a simple TCP client, and although the client works just fine in the foreground, daemonizing it causes strange behavior. 我正在尝试守护一个简单的TCP客户端,虽然客户端在前台工作得很好,但守护它会导致奇怪的行为。

As a test case, I have a server that, once you connect and send a single message ("connected"), will send you the number of seconds connected once per second. 作为一个测试用例,我有一台服务器,一旦你连接并发送一条消息(“已连接”),它将向你发送每秒连接一次的秒数。

If I daemonize (by calling Test::Connect(true) ), the connection drops after an arbitrary amount of time, even after successfully receiving a few numbers. 如果我守护进程(通过调用Test::Connect(true) ),连接会在任意时间后丢失,即使在成功接收到一些数字之后也是如此。

If I don't daemonize (by calling Test::Connect(false) ), the connection stays active and I continue to receive numbers as expected. 如果我没有守护进程(通过调用Test::Connect(false) ),连接保持活动状态,我会继续按预期接收数字。

#include <string>
#include <iostream>
#include <boost/asio.hpp>
#include <unistd.h>
class Test
{
  public:
    Test()
    {
      io = nullptr;
    }
    void Connect(bool daemonize)
    {
      io = new boost::asio::ip::tcp::iostream("localhost", "6500");
      if ( io && *io )
      {
        *io << "connected" << std::endl;

        if ( daemonize )
        {
          pid_t child = fork();
          if ( child < 0 ) exit(EXIT_FAILURE);
          else if ( child > 0 ) exit(EXIT_SUCCESS);

          umask(0);
          if ( setsid() < 0 ) exit(EXIT_FAILURE);
          if ( chdir("/tmp") < 0 ) exit(EXIT_FAILURE);

          child = fork();
          if ( child < 0 ) exit(EXIT_FAILURE);
          else if ( child > 0 ) exit(EXIT_SUCCESS);
        }

        std::string line;
        while ( *io )
        {
          std::getline(*io, line);
          std::cout << "Line (" << line.length() << "): " << line << std::endl;
        }
      }
      delete io;
      io = nullptr;
    }
  private:
    boost::asio::ip::tcp::iostream *io;
}

I'm absolutely stumped as to what could be cutting off the input stream early (it appears that the loop exits because io->eof() == true and thus (bool)*io == false ). 我很清楚可能会早期切断输入流(似乎循环退出,因为io->eof() == true ,因此(bool)*io == false )。 Since this only happens when trying to daemonize, should I avoid forking altogether? 因为这只是在尝试守护时发生的,我应该完全避免分叉吗? Is there a better way to send the process into the background programmatically (using C/C++ code only)? 有没有更好的方法以编程方式将进程发送到后台(仅使用C / C ++代码)?

I'm not sure if this is relevant, but do you need to call notify_fork here, eg: 我不确定这是否相关,但是你需要在这里调用notify_fork ,例如:

boost::asio::io_service io_service;
// ...
if ( daemonize )
{
  io_service.notify_fork(boost::asio::io_service::fork_prepare);
  pid_t child = fork();
  if (child == 0) io_service.notify_fork(boost::asio::io_service::fork_child);
  else io_service.notify_fork(boost::asio::io_service::fork_parent);
  // ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM