6

単純な TCP クライアントをデーモン化しようとしています。クライアントはフォアグラウンドで正常に動作しますが、デーモン化すると奇妙な動作が発生します。

テストケースとして、接続して単一のメッセージ(「接続済み」)を送信すると、1秒に1回接続された秒数を送信するサーバーがあります。

(を呼び出してTest::Connect(true)) デーモン化すると、いくつかの番号を正常に受信した後でも、任意の時間が経過すると接続が切断されます。

(を呼び出して) デーモン化しない場合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;
}

何が入力ストリームを早期に遮断する可能性があるのか​​ について、私は絶対に困惑しています(ループが終了するように見えるためio->eof() == true、およびしたがって(bool)*io == false)。これはデーモン化しようとしたときにのみ発生するため、フォークを完全に回避する必要がありますか? プログラムでプロセスをバックグラウンドに送信するより良い方法はありますか (C/C++ コードのみを使用)。

4

1 に答える 1

0

これが関連しているかどうかはわかりませんが、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);
  // ...
}
于 2013-01-10T15:15:57.093 に答える