diff --git a/main/sched.c b/main/sched.c index e3a7d30ec8..b759390306 100644 --- a/main/sched.c +++ b/main/sched.c @@ -98,6 +98,8 @@ struct sched { ast_cond_t cond; /*! Indication that a running task was deleted. */ unsigned int deleted:1; + /*! Indication that a running task was rescheduled. */ + unsigned int rescheduled:1; }; struct sched_thread { @@ -611,6 +613,7 @@ int ast_sched_del(struct ast_sched_context *con, int id) { struct sched *s = NULL; int *last_id = ast_threadstorage_get(&last_del_id, sizeof(int)); + int res = 0; DEBUG(ast_debug(1, "ast_sched_del(%d)\n", id)); @@ -646,6 +649,13 @@ int ast_sched_del(struct ast_sched_context *con, int id) ast_cond_wait(&s->cond, &con->lock); } /* Do not sched_release() here because ast_sched_runq() will do it */ + /* This was not rescheduled so the caller of ast_sched_del can not remove any + * references as they already were. + */ + if (!s->rescheduled) { + res = -2; + } + sched_release(con, s); } } @@ -668,7 +678,7 @@ int ast_sched_del(struct ast_sched_context *con, int id) return -1; } - return 0; + return res; } void ast_sched_report(struct ast_sched_context *con, struct ast_str **buf, struct ast_cb_names *cbnames) @@ -793,7 +803,9 @@ int ast_sched_runq(struct ast_sched_context *con) con->currently_executing = NULL; ast_cond_signal(¤t->cond); - if (res && !current->deleted) { + if (current->deleted) { + current->rescheduled = res ? 1 : 0; + } else if (res) { /* * If they return non-zero, we should schedule them to be * run again.