The code in main_loop_wait() which handles dispatching of IOHandlers only checks the 'deleted' flag once per iteration. If a handler was registered for both read & write events initially, and the read callback removes the handler, then the write callback will be set to NULL. If select() reported that there was a write event pending as well, then this will lead to QEMU crashing when trying to invoke the NULL write callback. A similar problem occurs if the handler was registered for read+write, and the read handler updates it to only select for read in the future - the write callback will be set to NULL. The attached patch adds neccessary checks to protect against this problem.
Signed-off-by: Daniel P. Berrange <[EMAIL PROTECTED]> Regards, Dan. -- |=- Red Hat, Engineering, Emerging Technologies, Boston. +1 978 392 2496 -=| |=- Perl modules: http://search.cpan.org/~danberr/ -=| |=- Projects: http://freshmeat.net/~danielpb/ -=| |=- GnuPG: 7D3B9505 F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 -=|
diff -r 25b9628b6900 vl.c --- a/vl.c Wed Aug 08 15:02:59 2007 -0400 +++ b/vl.c Mon Aug 13 15:02:22 2007 -0400 @@ -6453,12 +6453,10 @@ void main_loop_wait(int timeout) IOHandlerRecord **pioh; for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { - if (ioh->deleted) - continue; - if (FD_ISSET(ioh->fd, &rfds)) { + if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { ioh->fd_read(ioh->opaque); } - if (FD_ISSET(ioh->fd, &wfds)) { + if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { ioh->fd_write(ioh->opaque); } }