diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-02-28 21:59:44 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-02-28 21:59:44 +0000 |
commit | cafffd4024b10ac1eae54b74a5a0f372d86eede7 (patch) | |
tree | ce03ba4810c818fc93c866ad2bf9ba88c1379780 /vl.c | |
parent | 9542611a66227ceca062eec86d49e17aa79cbf90 (diff) |
Make removing IOHandlers safe from within an IOHandler, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2461 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 28 |
1 files changed, 22 insertions, 6 deletions
@@ -4462,6 +4462,7 @@ typedef struct IOHandlerRecord { IOCanRWHandler *fd_read_poll; IOHandler *fd_read; IOHandler *fd_write; + int deleted; void *opaque; /* temporary data */ struct pollfd *ufd; @@ -4487,8 +4488,7 @@ int qemu_set_fd_handler2(int fd, if (ioh == NULL) break; if (ioh->fd == fd) { - *pioh = ioh->next; - qemu_free(ioh); + ioh->deleted = 1; break; } pioh = &ioh->next; @@ -4509,6 +4509,7 @@ int qemu_set_fd_handler2(int fd, ioh->fd_read = fd_read; ioh->fd_write = fd_write; ioh->opaque = opaque; + ioh->deleted = 0; } return 0; } @@ -6157,7 +6158,7 @@ void qemu_system_powerdown_request(void) void main_loop_wait(int timeout) { - IOHandlerRecord *ioh, *ioh_next; + IOHandlerRecord *ioh; fd_set rfds, wfds, xfds; int ret, nfds; struct timeval tv; @@ -6192,6 +6193,8 @@ void main_loop_wait(int timeout) FD_ZERO(&wfds); FD_ZERO(&xfds); for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { + if (ioh->deleted) + continue; if (ioh->fd_read && (!ioh->fd_read_poll || ioh->fd_read_poll(ioh->opaque) != 0)) { @@ -6219,9 +6222,11 @@ void main_loop_wait(int timeout) #endif ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); if (ret > 0) { - /* XXX: better handling of removal */ - for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { - ioh_next = ioh->next; + IOHandlerRecord **pioh; + + for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { + if (ioh->deleted) + continue; if (FD_ISSET(ioh->fd, &rfds)) { ioh->fd_read(ioh->opaque); } @@ -6229,6 +6234,17 @@ void main_loop_wait(int timeout) ioh->fd_write(ioh->opaque); } } + + /* remove deleted IO handlers */ + pioh = &first_io_handler; + while (*pioh) { + ioh = *pioh; + if (ioh->deleted) { + *pioh = ioh->next; + qemu_free(ioh); + } else + pioh = &ioh->next; + } } #if defined(CONFIG_SLIRP) if (slirp_inited) { |