fix the fork() problem on MacOS (it existed on Linux, too, but ad no impact). New version 0.12.2 "(35) Bad Berleburg".

JSON-77
Roker 2018-03-13 14:42:54 +01:00
parent ce3eb2e9ee
commit dab4f13aaa
6 changed files with 41 additions and 16 deletions

View File

@ -2,9 +2,10 @@
#ifdef _WIN32
void daemonize()
void daemonize(std::function<void()> child_fn = std::function<void()>() )
{
// do nothing
if(child_fn)
child_fn();
}
#else
@ -18,7 +19,7 @@
#include <stdexcept>
void daemonize()
void daemonize(std::function<void()> child_fn )
{
/* already a daemon */
if ( getppid() == 1 ) return;
@ -36,6 +37,8 @@ void daemonize()
}
/* At this point we are executing as the child process */
if(child_fn)
child_fn();
/* Create a new SID for the child process */
pid_t sid = setsid();

View File

@ -1,8 +1,11 @@
#ifndef JSON_SERVER_ADAPTER_DAEMONIZE_HH
#define JSON_SERVER_ADAPTER_DAEMONIZE_HH
#include <functional>
// fork(), go into background, close all ttys etc...
// child_fn is called in the child process, before it detaches from the tty.
// system-specific! (POSIX, Windows, ...?)
void daemonize();
void daemonize( std::function<void()> child_fn = std::function<void()>() );
#endif

View File

@ -91,6 +91,9 @@ R call_with_lock( R(*fn)(Args...), Args... args)
} // end of anonymous namespace
PEP_SESSION JsonAdapter::first_session = nullptr;
typedef std::pair<std::string, unsigned> EventListenerKey;
struct EventListenerValue
@ -535,22 +538,21 @@ void JsonAdapter::prepare_run(const std::string& address, unsigned start_port, u
ev_server::setLogfile( &i->Log );
if(first_session == nullptr) // okay, we are the 1st:
{
// create a dummy session just to see whether the Engine is functional.
// reason: here we still can log errors to stderr, because prepare_run() is called before daemonize().
PEP_SESSION dummy_session = nullptr;
PEP_STATUS status = call_with_lock(&init, &dummy_session);
if(status != PEP_STATUS_OK || dummy_session==nullptr)
PEP_STATUS status = call_with_lock(&init, &first_session);
if(status != PEP_STATUS_OK || first_session==nullptr)
{
const std::string error_msg = "Cannot create session! PEP_STATUS: " + status_to_string(status) + ".";
const std::string error_msg = "Cannot create first session! PEP_STATUS: " + status_to_string(status) + ".";
std::cerr << error_msg << std::endl; // Log to stderr intentionally, so Enigmail can grab that error message easily.
if( ! i->ignore_session_error)
{
throw std::runtime_error(error_msg);
}
}
call_with_lock(&release, dummy_session);
// if we are here the Engine is able to create sessions. :-)
}
Log() << "ThreadFunc: thread id " << std::this_thread::get_id() << ". \n Registry: " << to_string( session_registry ) << std::flush;
@ -800,6 +802,13 @@ void JsonAdapter::check_guard() const
}
void JsonAdapter::global_shutdown()
{
call_with_lock(&release, JsonAdapter::first_session);
JsonAdapter::first_session = nullptr;
}
namespace {
std::string to_string(const SessionRegistry& reg)

View File

@ -86,6 +86,10 @@ public:
// will throw logic_error if guard variables contains illegal values, which means: *this is not a valid JsonAdapter object!
void check_guard() const;
// calls release(first_session).
static
void global_shutdown();
//private:
struct Internal;
@ -99,6 +103,9 @@ private:
void threadFunc();
std::exception_ptr initExcept;
// albait not documented, the first PEP_SESSION is special: It must be alive as long as any other PEP_SESSIONS are living.
static PEP_SESSION first_session;
};
// just for debug:

View File

@ -83,10 +83,11 @@ try
.ignore_session_errors( ignore_missing_session)
;
ja.prepare_run(address, start_port, end_port);
auto prepare_run = [&](){ ja.prepare_run(address, start_port, end_port); };
if( debug_mode )
{
prepare_run();
ja.run();
// run until "Q" from stdin
int input = 0;
@ -96,7 +97,7 @@ try
std::cout << "Oh, I got a '" << input << "'. \n";
}while(std::cin && input != 'q' && input != 'Q');
}else{
daemonize();
daemonize(prepare_run);
ja.run();
do{
std::this_thread::sleep_for(std::chrono::seconds(3));
@ -104,6 +105,7 @@ try
}
ja.shutdown(nullptr);
ja.Log() << "Good bye. :-)" << std::endl;
JsonAdapter::global_shutdown();
}
catch (std::exception const &e)
{

View File

@ -41,13 +41,14 @@ static const std::string version_name =
// "(31) Altenkleusheim"; // JSON-57: change location of server token file. breaking API change, so API_VERSION=0x0003.
// "(32) Littfeld"; // JSON-72: add is_pep_user() to the API
// "(33) Hilchenbach"; // JSON-71: Setup C++11 Multi-threading in libevent properly to avoid deadlocks in MT server code"
"(34) Erndtebrück"; // remove apiVersion(), change version() to return a semver-compatible version number in a JSON object.
// "(34) Erndtebrück"; // remove apiVersion(), change version() to return a semver-compatible version number in a JSON object.
"(35) Bad Berleburg"; // fix the fork() problem on MacOS. daemonize() now got a function parameter. \o/
//const ServerVersion sv{0, 10, 0, version_name}; // first version defined.
//const ServerVersion sv{0, 11, 0, version_name}; // add set_own_key()
//const ServerVersion sv{0, 12, 0, version_name}; // rename mis-spelled undo_last_mitrust() into undo_last_mistrust()
const ServerVersion sv{0, 12, 1, version_name}; // add assert_utf8() for every string to/from the Engine (except blobdata)
//const ServerVersion sv{0, 12, 1, version_name}; // add assert_utf8() for every string to/from the Engine (except blobdata)
const ServerVersion sv{0, 12, 2, version_name}; // fix the fork() problem on MacOS. daemonize() now got a function parameter.
} // end of anonymous namespace
////////////////////////////////////////////////////////////////////////////