tags:

views:

33

answers:

2

Hi,

Most of time my GLib program runs well. However, when logs like

** (process:pid): Message (recursed): blah lah blah

appear, the program will abort.

GLib manual says G_LOG_FLAG_RECURSION is considered fatal by default.

But I just can't understand what does "recursive messages" mean? When will recursed message occur?

Thanks

+1  A: 

Skimming through glib/gmessages.c gives me the very strong impression that G_LOG_FLAG_RECURSION is set if g_logv() needs to log an error itself.

Consider running out of memory; when a memory allocation attempt fails, the program will try to log the memory allocation failure, and probably exit. When the logging routine attempts to allocate memory to log the message, it is probably going to fail. So, the logging routines keep track of how 'deep' they have been called, and switch memory allocation strategy (they allocate on the stack instead of on the heap), if it is a recursive logging call.

Anytime the logging routines get an error message and would want to log the error, something really bad is going on, so it makes sense to try to log with another mechanism and then exit.

So you're probably just seeing a far-off symptom of the real problem. You could use ltrace(1) to try to spot the problem, or you could enable core dumps (ulimit -c unlimited) and try to find the call chain that causes the program to crash using gdb's bt command.

sarnold
+1  A: 

Note that a recursive call to a g_* logging routine can also happen if you are registering a custom handler (with g_log_set_handler) and that handler (or one of its callees) tries to log an error with a call to a g_* routine.

Also note that glib decided that any recursion should also be fatal (even if non-infinite of just one-level deep). This certainly makes sense for the case described in sarnold's answer of recursion on internal failure, but might not be obvious when trying to fix the issue in the case of a custom handler recurring. So, glib detects recursion as early as the first recursive call to g_*; it does not even get to checking whether your custom handler is attached. Hence, you will never see a recursive call into your handler. All this means that efforts such as carefully unregistering the handler inside the handler's body (and similar things) are futile.

You have to make absolutely sure that nothing down the call stack from your custom handler will ever call a g_* routine (which can get tricky if you handler calls into outside code and does complicate things like trying to deliver the log message to a remote destination or something).

alexei