2013-01-10 3 views
6

Ich versuche, einen einfachen TCP-Client zu dämonisieren, und obwohl der Client im Vordergrund gut funktioniert, verursacht die Daemonisierung seltsames Verhalten.Ist es sicher, fork() mit boost :: asio :: ip :: tcp :: iostream zu verwenden?

Als Testfall habe ich einen Server, der Ihnen nach dem Verbinden und Senden einer einzelnen Nachricht ("connected") die Anzahl der Sekunden sendet, die einmal pro Sekunde verbunden sind.

Wenn ich dämoniere (durch den Aufruf Test::Connect(true)), fällt die Verbindung nach einer willkürlichen Zeitspanne ab, selbst nachdem einige Nummern erfolgreich empfangen wurden.

Wenn ich nicht dämoniere (durch den Aufruf Test::Connect(false)), bleibt die Verbindung aktiv und ich bekomme weiterhin Nummern wie erwartet.

#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; 
} 

ich absolut ratlos bin, was könnte früh, um den Eingangsstrom werden abgeschnitten (es scheint, dass die Schleife beendet, weil io->eof() == true und damit (bool)*io == false). Da dies nur passiert, wenn man versucht, zu dämonisieren, sollte ich vermeiden, ganz zu forken? Gibt es eine bessere Möglichkeit, den Prozess programmgesteuert in den Hintergrund zu senden (nur mit C/C++ - Code)?

Antwort

0

Ich bin mir nicht sicher, ob dies relevant ist, aber tun Sie notify_fork hier, z.B .:

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

ist ein 'io_service' erforderlich, wenn Forking anrufen müssen? Ich könnte mich irren, aber ich dachte immer "io_service" war für asynchronen Code. – hydroiodic

+0

Ich weiß es nicht, aber es könnte einen Versuch wert sein. –

+0

Das 'io_service_' -Objekt, das in Ihrer Bearbeitung angegeben wurde, scheint nicht an irgendetwas gebunden zu sein; da 'class Test' einen Client beschreibt (mit synchroner Verwendung von' tcp :: iostream'), bin ich verwirrt über die Relevanz der Verwendung eines 'io_service'. Ist die einzige Möglichkeit, mit einem 'tcp :: iostream 'zu verzweigen, indem asynchrone Aufrufe mit einem' io_service' verwendet werden? – hydroiodic

Verwandte Themen