2013-01-10 15 views
6

Próbuję zdememonizować zwykłego klienta TCP i chociaż klient działa dobrze na pierwszym planie, jego demonizacja powoduje dziwne zachowanie.Czy można bezpiecznie używać fork() z boost :: asio :: ip :: tcp :: iostream?

W przypadku testowym mam serwer, który po podłączeniu i wysłaniu pojedynczej wiadomości ("podłączony") wyśle ​​liczbę sekund połączonych raz na sekundę.

Jeśli darzę demonem (przez wywołanie Test::Connect(true)), połączenie zostanie przerwane po dowolnym czasie, nawet po pomyślnym otrzymaniu kilku numerów.

Jeśli nie daemonizuję (przez wywołanie Test::Connect(false)), połączenie pozostaje aktywne i nadal otrzymuję numery zgodnie z oczekiwaniami. (Wydaje się, że wyjścia pętli bo io->eof() == true a więc (bool)*io == 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; 
} 

Jestem absolutnie zakłopotany, co może być odcięcie strumienia wejściowego wcześnie. Ponieważ tak się dzieje tylko podczas próby demonizacji, czy powinienem unikać całkowicie rozwidlenia? Czy istnieje lepszy sposób, aby przesłać proces w tle programowo (tylko przy użyciu kodu C/C++)?

Odpowiedz

0

Nie jestem pewien, czy to istotne, ale czy trzeba zadzwonić notify_fork tutaj, np .:

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); 
    // ... 
} 
+0

jest 'io_service' wymagane, jeśli rozwidlone? Mogę się mylić, ale zawsze myślałem, że "io_service" dotyczy asynchronicznego kodu. – hydroiodic

+0

Nie wiem, ale warto spróbować. –

+0

Obiekt 'io_service_' podany w edytorze nie wydaje się być związany z niczym; ponieważ 'test klasy' opisuje klienta (z synchronicznym użyciem' tcp :: iostream'), jestem zdezorientowany co do znaczenia używania 'io_service'. Czy jest to jedyny właściwy sposób na rozwidlenie z 'tcp :: iostream' przy użyciu wywołań asynchronicznych z' io_service'? – hydroiodic