I have a multithreaded program in C++. The problem I face while trying to print something in the log through multiple threads and program crashes. The specific problem is that I have cout << "some log message" << endl; And when I see the pstack for the dumped core, it shows that endl caused the problem of contention. On one thread, I have:
ff308edc _IO_do_write (ff341f28, ff341f6f, 2, ff341f6f, fc532a00, ff141f74) + dc
ff3094d8 _IO_file_overflow (ff341f28, a, ff000000, 1c00, 0, fffc00) + 2a8
ff3101fc overflow__7filebufi (ff341f28, a, 0, 1ffee, 7f2082, ff1b4f18) + 8
ff314010 overflow__8stdiobufi (a, a, ff314000, 4, fc532a00, fbdfbd51) + 10
ff306dd4 __overflow (ff341f28, a, 4, ff1b5434, ff1b5784, 82c8c) + 20
ff30fdd0 _IO_putc (a, ff341f28, 7d5be4, ff314048, ff1b5784, 82c8c) + 34
ff313088 endl__FR7ostream (7d5be0, 20, fbdfbd4e, 1, 0, 76f) + c
ff32a3f8 __ls__7ostreamPFR7ostream_R7ostream (7d5be0, 3bfb74, 3bf800, 385cd8, 76f, 0) + 4
On another thread, I have:
--- called from signal handler with signal 11 (SIGSEGV) ---
ff312f20 flush__7ostream (7d5be0, a, 4, ff1b5434, ff1b5784, 82c8c) + 10
ff312f58 flush__FR7ostream (7d5be0, ff341f28, 7d5be4, ff314048, ff1b5784, 82c8c) + 4
ff313090 endl__FR7ostream (7d5be0, 20, fbffbd4e, 1, 0, 232a) + 14
std::cout is buffered, and std::endl forces a flush of the output stream. So, it seems that on one thread endl is doing the flushing of the buffer while the other thread is trying to putc the newline characeter and hits an overflow.
Possible solutions (but have issues) could be: (1) Have an independent thread safe logger class that can be used for all log output, so instead of using std::cout we may use logger::cout in all places -- that's tedious as logging is scattered all over the place. also, to make this thread safe, mutex lock and unlock needs to be before and after each attempt to call insertion operator << or manipularors like endl. That's a performance hit. (2) Instead of using endl, we may use '\n' instead, so that flushing is not forced on every new line insertion, rather flushed when need be, by the underlying ostream buffering mechanism. But, is this thread safe? Not sure. (3) Switch to C++11 as C++11's std::cout is supposed to thread safe. But that's not immediately possible.
Any other better alternative or thoughts to get rid of SIGSEGV causing from endl manipulator by concurrent threads?
Can I somehow fore a synchronization / mutual exclusion while calling endl?