summaryrefslogtreecommitdiff
path: root/lib/pthreadpool/pthreadpool_tevent.c
diff options
context:
space:
mode:
authorStefan Metzmacher <metze@samba.org>2018-06-20 13:38:19 +0200
committerStefan Metzmacher <metze@samba.org>2018-07-12 14:25:19 +0200
commit25756425aaf5465e56ea809cd415b6a387848919 (patch)
tree3d0e0f838fc5f52d2d61d21f784e0bdc538855a0 /lib/pthreadpool/pthreadpool_tevent.c
parentfa070d90074629cb8262bc4e2a6ceef57a9fbd5c (diff)
downloadsamba-25756425aaf5465e56ea809cd415b6a387848919.tar.gz
pthreadpool: maintain a global list of orphaned pthreadpool_tevent_jobs
Instead of leaking the memory forever, we retry the cleanup, if other pthreadpool_tevent_*() functions are used. pthreadpool_tevent_cleanup_orphaned_jobs() could also be called by external callers. Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Ralph Boehme <slow@samba.org>
Diffstat (limited to 'lib/pthreadpool/pthreadpool_tevent.c')
-rw-r--r--lib/pthreadpool/pthreadpool_tevent.c41
1 files changed, 41 insertions, 0 deletions
diff --git a/lib/pthreadpool/pthreadpool_tevent.c b/lib/pthreadpool/pthreadpool_tevent.c
index e7396537058..5da1f22e91c 100644
--- a/lib/pthreadpool/pthreadpool_tevent.c
+++ b/lib/pthreadpool/pthreadpool_tevent.c
@@ -81,6 +81,24 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool);
static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job);
+static struct pthreadpool_tevent_job *orphaned_jobs;
+
+void pthreadpool_tevent_cleanup_orphaned_jobs(void)
+{
+ struct pthreadpool_tevent_job *job = NULL;
+ struct pthreadpool_tevent_job *njob = NULL;
+
+ for (job = orphaned_jobs; job != NULL; job = njob) {
+ njob = job->next;
+
+ /*
+ * The job destructor keeps the job alive
+ * (and in the list) or removes it from the list.
+ */
+ TALLOC_FREE(job);
+ }
+}
+
static int pthreadpool_tevent_job_signal(int jobid,
void (*job_fn)(void *private_data),
void *job_private_data,
@@ -92,6 +110,8 @@ int pthreadpool_tevent_init(TALLOC_CTX *mem_ctx, unsigned max_threads,
struct pthreadpool_tevent *pool;
int ret;
+ pthreadpool_tevent_cleanup_orphaned_jobs();
+
pool = talloc_zero(mem_ctx, struct pthreadpool_tevent);
if (pool == NULL) {
return ENOMEM;
@@ -164,6 +184,8 @@ static int pthreadpool_tevent_destructor(struct pthreadpool_tevent *pool)
}
pool->pool = NULL;
+ pthreadpool_tevent_cleanup_orphaned_jobs();
+
return 0;
}
@@ -317,10 +339,18 @@ static int pthreadpool_tevent_job_destructor(struct pthreadpool_tevent_job *job)
/*
* state->im still there means, we need to wait for the
* immediate event to be triggered or just leak the memory.
+ *
+ * Move it to the orphaned list, if it's not already there.
*/
return -1;
}
+ /*
+ * Finally remove from the orphaned_jobs list
+ * and let talloc destroy us.
+ */
+ DLIST_REMOVE(orphaned_jobs, job);
+
return 0;
}
@@ -362,6 +392,15 @@ static void pthreadpool_tevent_job_orphan(struct pthreadpool_tevent_job *job)
*/
DLIST_REMOVE(job->pool->jobs, job);
+ /*
+ * Add it to the list of orphaned jobs,
+ * which may be cleaned up later.
+ *
+ * The destructor removes it from the list
+ * when possible or it denies the free
+ * and keep it in the list.
+ */
+ DLIST_ADD_END(orphaned_jobs, job);
TALLOC_FREE(job);
}
@@ -400,6 +439,8 @@ struct tevent_req *pthreadpool_tevent_job_send(
struct pthreadpool_tevent_job *job = NULL;
int ret;
+ pthreadpool_tevent_cleanup_orphaned_jobs();
+
req = tevent_req_create(mem_ctx, &state,
struct pthreadpool_tevent_job_state);
if (req == NULL) {