better handling of removal in IOHandlerRecord list
PATCH 1/1 better handling of removal in IOHandlerRecord list
Hi,
by a call to qemu_set_fd_handler(fd,NULL,NULL,NULL) in the fd_read callback, I have generated a "Segmentation fault" in vl.c.
My solution is not very smart... but it is very simple.
Index: vl.c
===================================================================
RCS file: /sources/qemu/qemu/vl.c,v
retrieving revision 1.236
vl.c +5 -0
@@ -5926,6 +5926,11 @@if (FD_ISSET (ioh->fd, &rfds)) { ioh->fd_read (ioh->opaque); } + } +/* the IOHandlerRecord could have been removed from the list +and freed during ioh->fd_read call */ +for (ioh = first_io_handler; ioh !=NULL ; ioh = ioh_next) { + ioh_next = ioh->next;if (FD_ISSET (ioh->fd, &wfds)) { ioh->fd_write (ioh->opaque); }
Quoted 6 lines · jerome Arbez-Gindre
Hi,
by a call to
qemu_set_fd_handler(fd,NULL,NULL,NULL)in thefd_readcallback, I have generated a "Segmentation fault" invl.c.My solution is not very smart... but it is very simple.
I reply to myself because I did not sleep last night:
Here is the fix without the double IOHandlerRecord list iteration.
Index: vl.c
===================================================================
RCS file: /sources/qemu/qemu/vl.c,v
retrieving revision 1.236
vl.c +29 -32
@@ -4179,38 +4179,26 @@ IOHandler *fd_write, void *opaque) { -IOHandlerRecord **pioh, *ioh; +IOHandlerRecord *ioh; -if (!fd_read && !fd_write) { - pioh = &first_io_handler; -for (;;) { - ioh = *pioh; -if (ioh ==NULL ) -break ; -if (ioh->fd == fd) { - *pioh = ioh->next; -qemu_free (ioh); -break ; - } - pioh = &ioh->next; - } - }else { -for (ioh = first_io_handler; ioh !=NULL ; ioh = ioh->next) { -if (ioh->fd == fd) - goto found; - } - ioh =qemu_mallocz (sizeof (IOHandlerRecord)); -if (!ioh) -return -1 ; - ioh->next = first_io_handler; - first_io_handler = ioh; - found: - ioh->fd = fd; - ioh->fd_read_poll = fd_read_poll; - ioh->fd_read = fd_read; - ioh->fd_write = fd_write; - ioh->opaque = opaque; +for (ioh = first_io_handler; ioh !=NULL ; ioh = ioh->next) { +if (ioh->fd == fd) + goto found; } +if (!fd_read && !fd_write) +return 0 ; + ioh =qemu_mallocz (sizeof (IOHandlerRecord)); +if (!ioh) +return -1 ; + ioh->next = first_io_handler; + first_io_handler = ioh; +found: + ioh->fd = fd; + ioh->fd_read_poll = fd_read_poll; + ioh->fd_read = fd_read; + ioh->fd_write = fd_write; + ioh->opaque = opaque; +return 0 ; }
@@ -5858,7 +5846,7 @@void main_loop_wait (int timeout) { -IOHandlerRecord *ioh, *ioh_next; +IOHandlerRecord **pioh, *ioh, *ioh_next;fd_set rfds, wfds, xfds;int ret, nfds;struct timeval tv;
@@ -5921,14 +5909,23 @@ ret =select (nfds +1 , &rfds, &wfds, &xfds, &tv);if (ret >0 ) {/* XXX: better handling of removal */ + pioh = &first_io_handler ;for (ioh = first_io_handler; ioh !=NULL ; ioh = ioh_next) { ioh_next = ioh->next;if (FD_ISSET (ioh->fd, &rfds)) { ioh->fd_read (ioh->opaque); } -if (FD_ISSET (ioh->fd, &wfds)) { +/* ioh->fd_write could have been set to null */ +if ((ioh->fd_write) && (FD_ISSET (ioh->fd, &wfds))) { ioh->fd_write (ioh->opaque); } +/* the ioh could have been supressed */ +if (!ioh->fd_write && !ioh->fd_read) { + *pioh = ioh_next; +qemu_free (ioh); + }else { + pioh = &ioh->next ; + } } }#if defined(CONFIG_SLIRP )
Quoted 11 lines · jerome Arbez-Gindre
Quoted 6 lines · jerome Arbez-Gindre
Hi,
by a call to
qemu_set_fd_handler(fd,NULL,NULL,NULL)in thefd_readcallback, I have generated a "Segmentation fault" invl.c.My solution is not very smart... but it is very simple.
I reply to myself because I did not sleep last night:
Here is the fix without the double IOHandlerRecord list iteration.
Here is a little fix to handle the case when a IOHandler removes an other IOHandler.
vl.c renamed from vl.c.mine +4 -2
@@ -5912,11 +5912,13 @@ pioh = &first_io_handler ;for (ioh = first_io_handler; ioh !=NULL ; ioh = ioh_next) { ioh_next = ioh->next; -if (FD_ISSET (ioh->fd, &rfds)) { +/* ioh->fd_read could have been set to null by an other +IOHandlerRecord callback */ +if (ioh->fd_read &&FD_ISSET (ioh->fd, &rfds)) { ioh->fd_read (ioh->opaque); }/* ioh->fd_write could have been set to null */ -if ((ioh->fd_write) && (FD_ISSET (ioh->fd, &wfds))) { +if (ioh->fd_write &&FD_ISSET (ioh->fd, &wfds)) { ioh->fd_write (ioh->opaque); }/* the ioh could have been supressed */
I think a more complete patch is needed to fully correct the problem.
Regards,
Fabrice.
Quoted 47 lines · jerome Arbez-Gindre
Quoted 4 lines · jerome Arbez-Gindre
Quoted 2 lines · jerome Arbez-Gindre
Hi,
Quoted 8 lines
Quoted 4 lines
by a call to
qemu_set_fd_handler(fd,NULL,NULL,NULL)in thefd_readcallback, I have generated a "Segmentation fault" invl.c.My solution is not very smart... but it is very simple.
I reply to myself because I did not sleep last night:
Here is the fix without the double IOHandlerRecord list iteration.
Here is a little fix to handle the case when a IOHandler removes an other IOHandler.
vl.c renamed from vl.c.mine +4
-2@@ -5912,11 +5912,13 @@ pioh = &first_io_handler ;for (ioh = first_io_handler; ioh !=NULL ; ioh = ioh_next) { ioh_next = ioh->next; -if (FD_ISSET (ioh->fd, &rfds)) { +/* ioh->fd_read could have been set to null by an other +IOHandlerRecord callback */ +if (ioh->fd_read &&FD_ISSET (ioh->fd, &rfds)) { ioh->fd_read (ioh->opaque); }/* ioh->fd_write could have been set to null */ -if ((ioh->fd_write) && (FD_ISSET (ioh->fd, &wfds))) { +if (ioh->fd_write &&FD_ISSET (ioh->fd, &wfds)) { ioh->fd_write (ioh->opaque); }/* the ioh could have been supressed */ _______________________________________________
Qemu-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/qemu-devel