Qball's Weblog

Corner case crasher that I could hardly imagine

Tags gmpc 

In gmpc I have a function “process_itterate”  this handles (in idle time) the process_queue. (It does this by calling plugins (async))

process_itterates calles it self via g_idle_add() after a item is fully processed.  if it is called and process_queue is empty , it stops.

when a new item is injected when process_queue is empty, process_queue is also called via g_idle_add.

Now the crasher occured when:

process_queue emptied it queue and called *g_idle_add (call 1)
*

Directly after that a new query was placed, this sees an empty queue, and also calls *g_idle_add (call 2)
*

Then

call1 is handled

directly after that *call2 *is handled.

causing the same item in the queue being processed, leading to a crash.

The window of failure is _very very_ tiny.  process_itterate must just have emptied it queue and called it self, and between it calling g_idle_add and the handling of that call a new item has to be inserted.

This took me over a week and many very late hours to figure out. (as debugging stuff like this with gdb is near impossible, as idle calls screw up your backtrace).

The fix, a single line.

Make process_itterate not call itself (for the last time) when the queue is empty.