From: Gunnar Beutner Date: Tue, 30 Jul 2013 18:55:01 +0000 (+0200) Subject: Allow deleteschedule() to double-free schedules. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/f155b7da0075e0bd2304306d5231fe5d0e20fd02 Allow deleteschedule() to double-free schedules. --- diff --git a/core/schedule.c b/core/schedule.c index a8986bbe..77430285 100644 --- a/core/schedule.c +++ b/core/schedule.c @@ -166,6 +166,7 @@ void *scheduleoneshot(time_t when, ScheduleCallback callback, void *arg) { sp->repeatcount=1; sp->callback=callback; sp->callbackparam=arg; + sp->deleted=0; insertschedule(sp); @@ -191,6 +192,7 @@ void *schedulerecurring(time_t first, int count, time_t interval, ScheduleCallba sp->repeatcount=(count-1); sp->callback=callback; sp->callbackparam=arg; + sp->deleted=0; insertschedule(sp); @@ -211,13 +213,17 @@ void deleteschedule(void *sch, ScheduleCallback callback, void *arg) { if (sch) { sp=(schedule *)sch; /* Double check the params are correct: - * because we recycle and never free schedule structs it's - * actually OK to try and delete a schedule that has been executed... */ + * it's perfectly OK to delete a schedule that has been executed, + * we're just marking the schedule as deleted here so that it can be + * cleaned up by doscheduledevents later on. */ - if (sp->callback==callback && sp->callbackparam==arg) { + if (sp->callback==callback && sp->callbackparam==arg && !sp->deleted) { scheddelfast++; - schedule_remove(sp->index); - freeschedule(sp); + sp->deleted=1; +#ifdef SCHEDDEBUG + } else { + Error("schedule",ERR_DEBUG,"deleted schedule that was previously marked as deleted"); +#endif } return; } @@ -225,10 +231,9 @@ void deleteschedule(void *sch, ScheduleCallback callback, void *arg) { /* Argh, have to find it by brute force */ for(i=0;icallback==callback) && (events[i]->callbackparam==arg)) { + if (events[i]->callback==callback && events[i]->callbackparam==arg && !sp->deleted) { sp=events[i]; - schedule_remove(sp->index); - freeschedule(sp); + sp->deleted=1; return; } } @@ -266,7 +271,13 @@ void doscheduledevents(time_t when) { events[0]=events[heapsize]; events[0]->index=0; schedule_heapify(0); - + + /* This schedule was previously marked as deleted and we're now lazily cleaning it up. */ + if (sp->deleted) { + freeschedule(sp); + continue; + } + if (sp->callback==NULL) { Error("core",ERR_ERROR,"Tried to call NULL function in doscheduledevents(): (%p, %p, %p)",sp,sp->callback,sp->callbackparam); continue; @@ -279,7 +290,7 @@ void doscheduledevents(time_t when) { /* Update the structures _before_ doing the callback.. */ switch(sp->type) { case SCHEDULE_ONESHOT: - freeschedule(sp); + sp->deleted=1; break; case SCHEDULE_REPEATING: @@ -296,9 +307,11 @@ void doscheduledevents(time_t when) { sp->type=SCHEDULE_ONESHOT; } } - insertschedule(sp); break; } + + insertschedule(sp); + #ifdef SCHEDDEBUG Error("schedule",ERR_DEBUG,"exec schedule:(%x, %x, %x)", (unsigned int)sp, (unsigned int)sc, (unsigned int)arg); #endif diff --git a/core/schedule.h b/core/schedule.h index 7d1d586b..4f8eee5a 100644 --- a/core/schedule.h +++ b/core/schedule.h @@ -18,6 +18,7 @@ typedef struct schedule { ScheduleCallback callback; void *callbackparam; int index; /* Where in the array this event is currently situated */ + int deleted; } schedule;