Author Topic: cbAssert() kills everything on Linux  (Read 5315 times)

Offline XayC

  • Multiple posting newcomer
  • *
  • Posts: 94
cbAssert() kills everything on Linux
« on: December 12, 2007, 10:35:23 pm »
While developing a plugin I tried to use the debugging facilities offered by CB, including cbAssert(). What I found is that this function, when the assertion fails, it is supposed to terminate the application (in this case Code::Blocks) but on Linux it terminates all my processes, forcing a new login.

This behavior seems to be caused by the macro DIE, which is called after the assertion message is outputted. The macro is defined in this way, in the file cbexception.h.
Code
#ifdef __WXMSW__
   #define DIE() exit(1)
#else
   #include <csignal>
   #define DIE() kill(0, SIGTERM)
#endif

According to the kill() function documentation, sending a signal to pid 0 means:
If pid is 0, sig shall be sent to all processes (excluding an unspecified set of system processes) whose process group ID is equal to the process group ID of the sender, and for which the process has permission to send a signal.

I guess this macro should send the signal only to the calling process, not to every process having the same group ID. Am I wrong?

As a side note, it would be nice to have the CB assert functions, on Linux, show a message dialog too, like they do on Windows. Currently wxSafeShowMessage() shows a message box only on Windows, while it simply prints the message on the standard output on Linux. This could be accomplished adding an optional call to wxMessageBox() instead of wxSafeShowMessage().

Regards, XayC
« Last Edit: December 12, 2007, 10:47:11 pm by XayC »

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: cbAssert() kills everything on Linux
« Reply #1 on: December 13, 2007, 09:29:40 am »
While I've neither written this code (blame says mandrav), nor ever used it, I guess that I know the reason why it's written like that. The same process group should normally be only Code::Blocks and any running child processes like for example gcc, gdb, or a program that you develop and run/debug from inside Code::Blocks.

So, when that assertion fails, Code::Blocks does not exit and leave half a dozen orphans behind, but instead tells all its children that they should exit (which they probably should too, as an assert failure is a rather strong indicator that something is seriously wrong). Other software (like many old-school pre-fork servers) uses the very same principle.

All other processes (not started from Code::Blocks) should have different process group identifiers, and thus be unaffected.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."

Offline XayC

  • Multiple posting newcomer
  • *
  • Posts: 94
Re: cbAssert() kills everything on Linux
« Reply #2 on: December 13, 2007, 09:45:40 am »
Yes, I see that killing only Code::Blocks would, in many cases, leave other orphans processes but the call kill(0, SIGTERM) is killing every process in the current session. Did you try a simple cbAssert(0) on Linux and see what you get?

Unless Code::Blocks creates a new Process Group (as explained here), the current behavior is wrong.
I did a simple check using the ps command and, on Ubuntu Linux, Code::Blocks PGRP is the same as all the other processes manually started by me, this means that kill(0, SIGTERM) will (as it does) kill all my processes.
I think this should be fixed because it makes the Assertion facilities on Linux unusable.

Regards, XayC

Offline thomas

  • Administrator
  • Lives here!
  • *****
  • Posts: 3979
Re: cbAssert() kills everything on Linux
« Reply #3 on: December 13, 2007, 09:50:00 am »
So it seems a setsid() is missing in the startup code.
"We should forget about small efficiencies, say about 97% of the time: Premature quotation is the root of public humiliation."