From 25541ea3bb96e9f143f0e23f8ac5b432f2f6f47a Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 9 Feb 2012 20:20:34 +0100 Subject: [PATCH] Main: Removing an already removed event is always safe. Also adding an already added hook is always safe. For other event types, we still refuse repeated adds. --- ucw/doc/relnotes.txt | 3 ++- ucw/main-rec.c | 8 +++++--- ucw/mainloop.c | 20 +++++++++++--------- ucw/mainloop.h | 14 +++++++++----- 4 files changed, 27 insertions(+), 18 deletions(-) diff --git a/ucw/doc/relnotes.txt b/ucw/doc/relnotes.txt index add13974..11b16617 100644 --- a/ucw/doc/relnotes.txt +++ b/ucw/doc/relnotes.txt @@ -23,7 +23,8 @@ Release notes or <> to clean up properly after fork(). ** Added support for <>. ** Added relative timers: <>. -** Modification of events from a running event handler should be always safe. +** Modification of events from a running event handler is always safe. +** Deleting an already deleted event is always safe. ** For any event type, it is possible to ask whether it is active (added to the mainloop) or not: <> and friends. ** A new mainloop front-end for asynchronous <> has been added. diff --git a/ucw/main-rec.c b/ucw/main-rec.c index df23427d..1db9942b 100644 --- a/ucw/main-rec.c +++ b/ucw/main-rec.c @@ -1,7 +1,7 @@ /* * UCW Library -- Main Loop: Record I/O * - * (c) 2011 Martin Mares + * (c) 2011--2012 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -51,9 +51,11 @@ rec_io_add(struct main_rec_io *rio, int fd) void rec_io_del(struct main_rec_io *rio) { + if (!rec_io_is_active(rio)) + return; + timer_del(&rio->timer); - if (hook_is_active(&rio->start_read_hook)) - hook_del(&rio->start_read_hook); + hook_del(&rio->start_read_hook); file_del(&rio->file); if (rio->read_buf) diff --git a/ucw/mainloop.c b/ucw/mainloop.c index 454ea81c..52a63489 100644 --- a/ucw/mainloop.c +++ b/ucw/mainloop.c @@ -1,7 +1,7 @@ /* * UCW Library -- Main Loop * - * (c) 2004--2011 Martin Mares + * (c) 2004--2012 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -355,7 +355,8 @@ file_del_ctx(struct main_context *m, struct main_file *fi) // XXX: Can be called on a non-current context DBG("MAIN: Deleting file %p (fd=%d)", fi, fi->fd); - ASSERT(file_is_active(fi)); + if (!file_is_active(fi)) + return; clist_unlink(&fi->n); m->file_cnt--; #ifdef CONFIG_UCW_EPOLL @@ -378,16 +379,16 @@ hook_add(struct main_hook *ho) struct main_context *m = main_current(); DBG("MAIN: Adding hook %p", ho); - ASSERT(!hook_is_active(ho)); - clist_add_tail(&m->hook_list, &ho->n); + if (!hook_is_active(ho)) + clist_add_tail(&m->hook_list, &ho->n); } void hook_del(struct main_hook *ho) { DBG("MAIN: Deleting hook %p", ho); - ASSERT(hook_is_active(ho)); - clist_unlink(&ho->n); + if (hook_is_active(ho)) + clist_unlink(&ho->n); } static void @@ -436,8 +437,8 @@ void process_del(struct main_process *mp) { DBG("MAIN: Deleting process %p (pid=%d)", mp, mp->pid); - ASSERT(process_is_active(mp)); - clist_unlink(&mp->n); + if (process_is_active(mp)) + clist_unlink(&mp->n); } int @@ -568,7 +569,8 @@ signal_del_ctx(struct main_context *m, struct main_signal *ms) // XXX: Can be called on a non-current context DBG("MAIN: Deleting signal %p (sig=%d)", ms, ms->signum); - ASSERT(signal_is_active(ms)); + if (!signal_is_active(ms)) + return; clist_unlink(&ms->n); int another = 0; diff --git a/ucw/mainloop.h b/ucw/mainloop.h index 6de703d8..9cd97453 100644 --- a/ucw/mainloop.h +++ b/ucw/mainloop.h @@ -1,7 +1,7 @@ /* * UCW Library -- Main Loop * - * (c) 2004--2011 Martin Mares + * (c) 2004--2012 Martin Mares * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -178,7 +178,7 @@ void timer_add_rel(struct main_timer *tm, timestamp_t expires_delta); /** * Removes a timer from the active ones. It is permitted (and common) to call * this function from the timer's handler itself if you want to deactivate - * the timer. + * the timer. Removing an already removed timer does nothing. **/ void timer_del(struct main_timer *tm); @@ -247,12 +247,14 @@ enum main_hook_return { * Inserts a new hook into the loop. * The hook will be scheduled at least once before next sleep. * May be called from inside a hook handler too. + * Adding an already added hook does nothing. **/ void hook_add(struct main_hook *ho); /** * Removes an existing hook from the loop. * May be called from inside a hook handler (to delete itself or another hook). + * Removing an already removed hook does nothing. **/ void hook_del(struct main_hook *ho); @@ -339,6 +341,7 @@ void file_chg(struct main_file *fi); * please use this function first. * * Can be called from a handler. + * Removing an already removed file does nothing. **/ void file_del(struct main_file *fi); @@ -391,7 +394,7 @@ struct main_block_io { /** Activate a block I/O structure. **/ void block_io_add(struct main_block_io *bio, int fd); -/** Deactivate a block I/O structure. **/ +/** Deactivate a block I/O structure. Calling twice is safe. **/ void block_io_del(struct main_block_io *bio); /** @@ -518,7 +521,7 @@ struct main_rec_io { /** Activate a record I/O structure. **/ void rec_io_add(struct main_rec_io *rio, int fd); -/** Deactivate a record I/O structure. **/ +/** Deactivate a record I/O structure. Calling twice is safe. **/ void rec_io_del(struct main_rec_io *rio); /** @@ -607,6 +610,7 @@ void process_add(struct main_process *mp); * Removes the process from the watched set. This is done * automatically, when the process terminates, so you need it only * when you do not want to watch a running process any more. + * Removing an already removed process does nothing. */ void process_del(struct main_process *mp); @@ -672,7 +676,7 @@ struct main_signal { /** Request a signal to be caught and delivered synchronously. **/ void signal_add(struct main_signal *ms); -/** Cancel a request for signal catching. **/ +/** Cancel a request for signal catching. Calling twice is safe. **/ void signal_del(struct main_signal *ms); /** Tells if a signal catcher is active (i.e., added). **/ -- 2.39.2