I'm hoping the hard core C++ guys will think about this a little and maybe have some suggestions. It's an esoteric enough problem that you might find it interesting. :-)
For complicated reasons, we sometimes end up trying to open a Thrift socket
connection to a local server process during client-side static init time. I
know that the simple answer would be "don't do that", but that's really not
possible.
This has worked just fine as long as the server process is running. If it is
not running, however, the client app has a high probability of crashing when
the socket connection attempt fails. This is because when such an error occurs,
the output is handled by calling GlobalOutput.perror, like so:
GlobalOutput.perror("TSocket::open() socket() " + getSocketInfo(),
errno_copy);
The problem is that GlobalOutput is a global object that is constructed at
static init time. Since we can't control the order in which global objects are
initialized, we may try to communicate before GlobalOutput has been
constructed. Thus the crash. (The situation is analogous to a global object
trying to connect to the server in the object's constructor. Depending on the
order of static init execution, GlobalOutput may or may not have been
constructed when the connection attempt is made.)
The GlobalOutput object is instantiated in Thrift.cpp with this line of code:
TOutput GlobalOutput;
The easy way to fix this problem is to wrap the global object in a "construct
on first use" function
(http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.15) like this:
TOutput &GlobalOutput (void)
{
static TOutput GlobalOutput;
return GlobalOutput;
}
which guarantees that it gets constructed the first time GlobalOuput() is
called, but then I will need to change every existing reference to GlobalOutput
to a function call to GlobalOutput(). So, for instance, the call to perror that
I pasted above would change to:
GlobalOutput().perror("TSocket::open() socket() " + getSocketInfo(),
errno_copy);
As usual, I have a list of questions (but it's short):
1) Can anyone think of another way around this problem?
2) Would the C++ library developers be at all receptive to taking the change I
have outlined (GlobalOutput -> GlobalOutput()) into the trunk? On one hand, it
adds a function call. On the other hand the operation in progress is formatted
output, so one extra function call to get the reference probably doesn't
matter. On yet the other hand, the change would have to extend to the server
side code as well, and probably you guys running large server side operations
worry about error performance more that I worry about client side performance
in the same situation.
TIA,
Rush
smime.p7s
Description: S/MIME cryptographic signature
