summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--event.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/event.c b/event.c
index a979f1f2..fab419af 100644
--- a/event.c
+++ b/event.c
@@ -1256,6 +1256,14 @@ done:
static inline void
event_persist_closure(struct event_base *base, struct event *ev)
{
+ // Define our callback, we use this to store our callback before it's executed
+ void (*evcb_callback)(evutil_socket_t, short, void *);
+
+ // Other fields of *ev that must be stored before executing
+ evutil_socket_t evcb_fd;
+ short evcb_res;
+ void *evcb_arg;
+
/* reschedule the persistent event if we have a timeout. */
if (ev->ev_io_timeout.tv_sec || ev->ev_io_timeout.tv_usec) {
/* If there was a timeout, we want it to run at an interval of
@@ -1297,8 +1305,18 @@ event_persist_closure(struct event_base *base, struct event *ev)
run_at.tv_usec |= usec_mask;
event_add_internal(ev, &run_at, 1);
}
- EVBASE_RELEASE_LOCK(base, th_base_lock);
- (*ev->ev_callback)(ev->ev_fd, ev->ev_res, ev->ev_arg);
+
+ // Save our callback before we release the lock
+ evcb_callback = ev->ev_callback;
+ evcb_fd = ev->ev_fd;
+ evcb_res = ev->ev_res;
+ evcb_arg = ev->ev_arg;
+
+ // Release the lock
+ EVBASE_RELEASE_LOCK(base, th_base_lock);
+
+ // Execute the callback
+ (evcb_callback)(evcb_fd, evcb_res, evcb_arg);
}
/*