Networking and threading belong together like Pepper and Iron Man.
- The implementation of publishTime must change if it's to be thread safe. The change is simple but important: we need to call a reentrant, thread safe version of gmtime called gmtime_r.
- gmtime returns a pointer to a single, statically allocated record of time information that's used by all calls to it. If two threads make competing calls to it, then both threads race to pull time information from the shared, statically allocated record.
- One solution is to use a mutex to ensure that a thread can call gmtime without competition and subsequently copy the data out of the static record into a local character buffer.
- Another solution—one that doesn't require locking and one I think is better—makes use of a second version of the same function called gmtime_r. The second, reentrant version just requires that space for a dedicated return value be passed in.
static void publishTime(int clientSocket) {
time_t rawtime;
time(&rawtime);
struct tm tm;
gmtime_r(&rawtime, &tm);
char timeString[128]; // more than big enough
/* size_t len = */ strftime(timeString, sizeof(timeString), "%c", &tm);
sockbuf sb(clientSocket); // destructor closes socket
iosockstream ss(&sb);
ss << timeString << endl;
}