Comment 33 for bug 849414

Revision history for this message
James Hunt (jamesodhunt) wrote :

I've disassembled the offending library code and looking at the register dump we can learn a little more....

Firstly, I now think the problem is *not* in ply_event_loop_process_pending_events() - it's in ply_event_loop_handle_timeouts(). The reason for the confusion is that it appears that gcc has optimized ply_event_loop_handle_timeouts() by inlining it into ply_event_loop_process_pending_events(). So, if we now look at ply_event_loop_handle_timeouts(), we can see the code that's causing plymouthd to die:

1216 while (node != NULL)
1217 {
1218 ply_list_node_t *next_node;
1219 ply_event_loop_timeout_watch_t *watch;
1220
1221 watch = (ply_event_loop_timeout_watch_t *) ply_list_node_get_data (node);
1222 next_node = ply_list_get_next_node (loop->timeout_watches, node);
1223
1224 if (watch->timeout <= now) /* XXX: crash is triggered here */
1225 {

The offending line is 1224. In assembler this equates to:

    test %ecx,0x4(%esi)

... where ecx=0x1 and esi = 0x0.

In pseudo-C-code though what is actually happening in plymouthd is:

  if ( NULL->timeout <= 1)

So the problem is that the timeout watch is NULL. Looking at the C code shows that no check is performed on 'watch' being NULL or not - it's just blindly dereferenced which causes the SIGSEGV. However, I can't yet see how watch is ever NULL, unless it's that pesky alloca causing undefined behaviour maybe.