I'm working on a server and I want to be able to log messages using log4cplus. Up to here nothing too complicated.
However, I use fork()
to create a child process each time I receive a connection request. The fork()
is to make sure that the child processes have their own instance of the database connection.
Now I'd like to make use of the Logger in the child as well. It works great in the server (i.e. I can see the log output in the console and the file as I set it up.) But after the fork()
it looks like it gets lost.
There is a simplified synopsis as it is used now:
log4cplus::PropertyConfigurator::doConfigure(filename);
log4cplus::Logger l(log4cplus::Logger::getInstance("snap"));
l.log(ll, "Server Started", f_file, f_line); // <<-- works great!
...
listen();
accept();
...
fork();
// if child:
log4cplus::Logger l(log4cplus::Logger::getInstance("snap"));
l.log(ll, msg, f_file, f_line); // <<-- does not work?!
I'm thinking that the logger may be locking the file in the server and thus the children cannot themselves open that same file. Is that the case? If so then log4cplus cannot be used in my environment...
As mentioned in the comments, to make it all work again, you want to close everything and reconfigure.
However, if you are using a newer version and the loggingserver you end up with at least one thread. In that situation, the fork()
will not duplicate the thread so calling log4cplus::Logger::shutdown
locks up if just called in the child process (it waits on that thread forever in the child process.)
So the proper way to do this is by shutting down in the parent, forking, then re-configuring in the parent and child. The following function shows how we can handle the situation.
pid_t fork_child()
{
// shutdown
log4cplus::Logger::shutdown();
pid_t p(fork());
// reconfigure
log4cplus::PropertyConfigurator::doConfigure("snap.properties");
return p;
}