Commit cafffd4024b10ac1eae54b74a5a0f372d86eede7
1 parent
9542611a
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
Showing
1 changed file
with
22 additions
and
6 deletions
vl.c
... | ... | @@ -4462,6 +4462,7 @@ typedef struct IOHandlerRecord { |
4462 | 4462 | IOCanRWHandler *fd_read_poll; |
4463 | 4463 | IOHandler *fd_read; |
4464 | 4464 | IOHandler *fd_write; |
4465 | + int deleted; | |
4465 | 4466 | void *opaque; |
4466 | 4467 | /* temporary data */ |
4467 | 4468 | struct pollfd *ufd; |
... | ... | @@ -4487,8 +4488,7 @@ int qemu_set_fd_handler2(int fd, |
4487 | 4488 | if (ioh == NULL) |
4488 | 4489 | break; |
4489 | 4490 | if (ioh->fd == fd) { |
4490 | - *pioh = ioh->next; | |
4491 | - qemu_free(ioh); | |
4491 | + ioh->deleted = 1; | |
4492 | 4492 | break; |
4493 | 4493 | } |
4494 | 4494 | pioh = &ioh->next; |
... | ... | @@ -4509,6 +4509,7 @@ int qemu_set_fd_handler2(int fd, |
4509 | 4509 | ioh->fd_read = fd_read; |
4510 | 4510 | ioh->fd_write = fd_write; |
4511 | 4511 | ioh->opaque = opaque; |
4512 | + ioh->deleted = 0; | |
4512 | 4513 | } |
4513 | 4514 | return 0; |
4514 | 4515 | } |
... | ... | @@ -6157,7 +6158,7 @@ void qemu_system_powerdown_request(void) |
6157 | 6158 | |
6158 | 6159 | void main_loop_wait(int timeout) |
6159 | 6160 | { |
6160 | - IOHandlerRecord *ioh, *ioh_next; | |
6161 | + IOHandlerRecord *ioh; | |
6161 | 6162 | fd_set rfds, wfds, xfds; |
6162 | 6163 | int ret, nfds; |
6163 | 6164 | struct timeval tv; |
... | ... | @@ -6192,6 +6193,8 @@ void main_loop_wait(int timeout) |
6192 | 6193 | FD_ZERO(&wfds); |
6193 | 6194 | FD_ZERO(&xfds); |
6194 | 6195 | for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { |
6196 | + if (ioh->deleted) | |
6197 | + continue; | |
6195 | 6198 | if (ioh->fd_read && |
6196 | 6199 | (!ioh->fd_read_poll || |
6197 | 6200 | ioh->fd_read_poll(ioh->opaque) != 0)) { |
... | ... | @@ -6219,9 +6222,11 @@ void main_loop_wait(int timeout) |
6219 | 6222 | #endif |
6220 | 6223 | ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); |
6221 | 6224 | if (ret > 0) { |
6222 | - /* XXX: better handling of removal */ | |
6223 | - for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { | |
6224 | - ioh_next = ioh->next; | |
6225 | + IOHandlerRecord **pioh; | |
6226 | + | |
6227 | + for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { | |
6228 | + if (ioh->deleted) | |
6229 | + continue; | |
6225 | 6230 | if (FD_ISSET(ioh->fd, &rfds)) { |
6226 | 6231 | ioh->fd_read(ioh->opaque); |
6227 | 6232 | } |
... | ... | @@ -6229,6 +6234,17 @@ void main_loop_wait(int timeout) |
6229 | 6234 | ioh->fd_write(ioh->opaque); |
6230 | 6235 | } |
6231 | 6236 | } |
6237 | + | |
6238 | + /* remove deleted IO handlers */ | |
6239 | + pioh = &first_io_handler; | |
6240 | + while (*pioh) { | |
6241 | + ioh = *pioh; | |
6242 | + if (ioh->deleted) { | |
6243 | + *pioh = ioh->next; | |
6244 | + qemu_free(ioh); | |
6245 | + } else | |
6246 | + pioh = &ioh->next; | |
6247 | + } | |
6232 | 6248 | } |
6233 | 6249 | #if defined(CONFIG_SLIRP) |
6234 | 6250 | if (slirp_inited) { | ... | ... |