[SCM] Samba Shared Repository - branch master updated

Stefan Metzmacher metze at samba.org
Thu Jul 12 15:19:10 UTC 2018


The branch, master has been updated
       via  3eee52b pthreadpool: allocate glue->tctx on glue as memory context.
       via  2575642 pthreadpool: maintain a global list of orphaned pthreadpool_tevent_jobs
       via  fa070d9 pthreadpool: make use of pthreadpool_stop() in pthreadpool_tevent_destructor()
       via  791c051 pthreadpool: add pthreadpool_tevent_job_cancel()
       via  245d684 pthreadpool: split out pthreadpool_tevent_job from pthreadpool_tevent_job_state
       via  cdbad90 pthreadpool: let pthreadpool_tevent_job_send() fail with an invalid pool
       via  f19552e pthreadpool: split out a pthreadpool_stop() from pthreadpool_destroy()
       via  5976841 pthreadpool: don't process further jobs when shutting down
       via  4e54543 pthreadpool: add pthreadpool_cancel_job()
       via  e4dfd3d pthreadpool: add pthreadpool_tevent_max_threads() and pthreadpool_tevent_queued_jobs()
       via  505d298 pthreadpool: add pthreadpool_max_threads() and pthreadpool_queued_jobs() helpers
       via  76474a6 pthreadpool: expand test_create() to check unlimited, sync and one thread pool
       via  f1dac71 pthreadpool: fix helgrind error in pthreadpool_free()
       via  c9f54db pthreadpool: use talloc_zero() in tests_cmocka.c setup_pthreadpool_tevent()
       via  e45d33e pthreadpool: use strict sync processing only with max_threads=0
       via  03830a3 pthreadpool: consitently use unlock_res for pthread_mutex_unlock() in pthreadpool_add_job()
       via  65faef9 s3:messages: explicitly use max_thread=unlimited for pthreadpool_tevent_init() in messaging_dgm_init()
       via  53a9f3c pthreadpool: explicitly use max_thread=unlimited for pthreadpool_tevent_init() tests
       via  5e723bc pthreadpool: use unsigned for num_idle, num_threads and max_threads
       via  19e4a08 pthreadpool: correctly handle pthreadpool_tevent_register_ev() failures
       via  c310647 smbd: remove unused change_to_root_user() from brl_timeout_fn()
       via  d0b1f96 smbd: remove unused change_to_root_user() from smbd_sig_hup_handler()
       via  e37e41b smbd: avoid explicit change_to_user() in defer_rename_done() already done by impersonation
       via  1b804f7 smbd: implement smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers
       via  0dcaa07 smbd: make use of smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers
       via  5285966 smbd: add simple noop smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers
       via  23319ef smbd: add smbd_impersonate_debug_create() helper
       via  7b5a47b smbd: add [un]become_guest() helper functions
      from  710ce1c WHATSNEW: Start release notes for Samba 4.10.

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 3eee52b44daa8544e1c1fb609f901a3a96b29b25
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 17:11:53 2018 +0200

    pthreadpool: allocate glue->tctx on glue as memory context.
    
    This means it will go aways together with glue and thte event context.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Thu Jul 12 17:18:01 CEST 2018 on sn-devel-144

commit 25756425aaf5465e56ea809cd415b6a387848919
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 20 13:38:19 2018 +0200

    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 at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit fa070d90074629cb8262bc4e2a6ceef57a9fbd5c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 25 20:25:21 2018 +0200

    pthreadpool: make use of pthreadpool_stop() in pthreadpool_tevent_destructor()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 791c05144ee9296024cc0fdebe4afeaaf67e26bc
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 25 14:43:22 2018 +0200

    pthreadpool: add pthreadpool_tevent_job_cancel()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 245d684d28dab630f3d47ff61006a1fe3e5eeefa
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 01:39:47 2018 +0200

    pthreadpool: split out pthreadpool_tevent_job from pthreadpool_tevent_job_state
    
    This makes it much easier to handle orphaned jobs,
    we either wait for the immediate tevent to trigger
    or we just keep leaking the memory.
    
    The next commits will improve this further.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit cdbad9041b8afd3f0436fbeb5d6b50f9f1ada60d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 20 15:07:08 2018 +0200

    pthreadpool: let pthreadpool_tevent_job_send() fail with an invalid pool
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit f19552e2390636518dc762bb9dfe25d3407dc521
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 25 14:03:30 2018 +0200

    pthreadpool: split out a pthreadpool_stop() from pthreadpool_destroy()
    
    This can be used in combination with pthreadpool_cancel_job() to
    implement a multi step shutdown of the pool.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 59768416148f72d87cba80ae21afbb2861ca9442
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 20 17:12:07 2018 +0200

    pthreadpool: don't process further jobs when shutting down
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 4e54543b54ea2bc71f5524a41d359376b8f59125
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 20 15:00:31 2018 +0200

    pthreadpool: add pthreadpool_cancel_job()
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit e4dfd3da94c097fa9cd3fea4ad6dfc4af8ca2a45
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 01:01:42 2018 +0200

    pthreadpool: add pthreadpool_tevent_max_threads() and pthreadpool_tevent_queued_jobs()
    
    These can be used to implement some kind of flow control in the caller.
    E.g. unless pthreadpool_tevent_queued_jobs() is lower than
    pthreadpool_tevent_max_threads() is good to prepare new jobs.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 505d298e81570bb118a9b82e5166a8f11139750b
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 00:49:33 2018 +0200

    pthreadpool: add pthreadpool_max_threads() and pthreadpool_queued_jobs() helpers
    
    These can be used to implement some kind of flow control in the caller.
    E.g. unless pthreadpool_queued_jobs() is lower than
    pthreadpool_max_threads() is good to prepare new jobs.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 76474a6fad43c791293f4fb30dc7c155619c5dec
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 08:39:36 2018 +0200

    pthreadpool: expand test_create() to check unlimited, sync and one thread pool
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit f1dac71a866857bc70a0477861997cc6174a00d9
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 21 12:40:30 2018 +0200

    pthreadpool: fix helgrind error in pthreadpool_free()
    
    We need to pthread_mutex_lock/unlock the pool mutex
    before we can destroy it.
    
    The following test would trigger this.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c9f54db10911762298d1d4fe681d0aaf705f6f55
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Jun 20 15:38:08 2018 +0200

    pthreadpool: use talloc_zero() in tests_cmocka.c setup_pthreadpool_tevent()
    
    This was found with valgrind.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit e45d33e92e47995faa7c523cf82dfb65efb190f8
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 00:29:53 2018 +0200

    pthreadpool: use strict sync processing only with max_threads=0
    
    Otherwise it's an error if not at least one thread is possible.
    
    This gives a much saner behaviour and doesn't end up with
    unexpected sync processing.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 03830a3226d43f13e58dcf68874d50e19793144d
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 00:27:39 2018 +0200

    pthreadpool: consitently use unlock_res for pthread_mutex_unlock() in pthreadpool_add_job()
    
    This makes further restructuring easier to implement and understand.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 65faef959d93221909d3d4031f685a442935ee90
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 00:10:08 2018 +0200

    s3:messages: explicitly use max_thread=unlimited for pthreadpool_tevent_init() in messaging_dgm_init()
    
    Currently 0 also means unlimited, but that will change soon,
    to force no thread and strict sync processing.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 53a9f3cac646c1034a15d2b54531b9be46dde923
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 00:10:08 2018 +0200

    pthreadpool: explicitly use max_thread=unlimited for pthreadpool_tevent_init() tests
    
    Currently 0 also means unlimited, but that will change soon,
    to force no thread and strict sync processing.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 5e723bc6f122223252b8d3c67b7b1f17121dd49a
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Jun 22 00:04:48 2018 +0200

    pthreadpool: use unsigned for num_idle, num_threads and max_threads
    
    These can't get negative.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 19e4a0857779dd7502d044fc76859bbc202276e2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Apr 20 15:05:44 2018 +0200

    pthreadpool: correctly handle pthreadpool_tevent_register_ev() failures
    
    It returns errno values instead of setting 'errno'.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit c310647e560abc2343ef2ff0ab15daab0fba2650
Author: Ralph Boehme <slow at samba.org>
Date:   Wed May 23 16:28:48 2018 +0200

    smbd: remove unused change_to_root_user() from brl_timeout_fn()
    
    This is handled by using the root_ev_ctx in order to register
    the timer event.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit d0b1f96f086bdd613644f64b3f75ee8c4388f674
Author: Stefan Metzmacher <metze at samba.org>
Date:   Wed Apr 18 14:29:52 2018 +0200

    smbd: remove unused change_to_root_user() from smbd_sig_hup_handler()
    
    This is handled by using the root_ev_ctx in order to register
    the signal event.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit e37e41b3cac52e3623f0c79f83733a51edb35c10
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Jun 21 19:20:53 2018 +0200

    smbd: avoid explicit change_to_user() in defer_rename_done() already done by impersonation
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 1b804f7ae23f54a6c1004e5ff17b9df1376b5adb
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 11 15:51:42 2012 +0200

    smbd: implement smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers
    
    This makes sure we're doing the correct impersonation for async
    requests, which is a requirement to start adding path based
    async SMB_VFS calls.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 0dcaa0707bad67f7bfaa10ccaf167bfefbe87a0c
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Mar 22 10:54:41 2018 +0100

    smbd: make use of smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers
    
    For now they just add debugging, but that will change shortly.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 5285966e67cbee8519015df12a15e938e85e6ee7
Author: Stefan Metzmacher <metze at samba.org>
Date:   Thu Mar 22 10:54:41 2018 +0100

    smbd: add simple noop smbd_impersonate_{conn_vuid,conn_sess,root,guest}_create() wrappers
    
    As a start these are just wrappers arround
    smbd_impersonate_debug_create(), without any real impersonation.
    But this will change shortly.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 23319ef5a2eff4811b685d4ab54179efc49bac99
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri Mar 23 07:47:38 2018 +0100

    smbd: add smbd_impersonate_debug_create() helper
    
    This will be used to implement no-op impersonation
    for the create_conn_struct_as_root() case were we
    don't really have other unrelated events in the loop
    and only need a valid tevent wrapper context to avoid
    double free on the raw event context on teardown.
    
    This also adds useful debugging instead of being
    a full no-op wrapper.
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

commit 7b5a47b84696e8e5c26207bd398742b883e598c2
Author: Stefan Metzmacher <metze at samba.org>
Date:   Fri May 25 16:22:33 2018 +0200

    smbd: add [un]become_guest() helper functions
    
    Signed-off-by: Stefan Metzmacher <metze at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>

-----------------------------------------------------------------------

Summary of changes:
 lib/pthreadpool/pthreadpool.c        |  245 +++++--
 lib/pthreadpool/pthreadpool.h        |   73 ++
 lib/pthreadpool/pthreadpool_sync.c   |   29 +
 lib/pthreadpool/pthreadpool_tevent.c |  354 ++++++++--
 lib/pthreadpool/pthreadpool_tevent.h |    5 +
 lib/pthreadpool/tests.c              |    3 +-
 lib/pthreadpool/tests_cmocka.c       |   86 ++-
 source3/lib/messages_dgm.c           |    2 +-
 source3/modules/vfs_readonly.c       |    2 +-
 source3/smbd/blocking.c              |    3 -
 source3/smbd/conn.c                  |    2 +-
 source3/smbd/msdfs.c                 |   34 +-
 source3/smbd/process.c               |   19 +-
 source3/smbd/proto.h                 |   19 +
 source3/smbd/smb2_setinfo.c          |   11 -
 source3/smbd/uid.c                   | 1236 +++++++++++++++++++++++++++++++++-
 16 files changed, 1968 insertions(+), 155 deletions(-)


Changeset truncated at 500 lines:

diff --git a/lib/pthreadpool/pthreadpool.c b/lib/pthreadpool/pthreadpool.c
index 92a88c9..610cfb0 100644
--- a/lib/pthreadpool/pthreadpool.c
+++ b/lib/pthreadpool/pthreadpool.c
@@ -71,24 +71,32 @@ struct pthreadpool {
 	void *signal_fn_private_data;
 
 	/*
-	 * indicator to worker threads that they should shut down
+	 * indicator to worker threads to stop processing further jobs
+	 * and exit.
 	 */
-	bool shutdown;
+	bool stopped;
+
+	/*
+	 * indicator to the last worker thread to free the pool
+	 * resources.
+	 */
+	bool destroyed;
 
 	/*
 	 * maximum number of threads
+	 * 0 means no real thread, only strict sync processing.
 	 */
-	int max_threads;
+	unsigned max_threads;
 
 	/*
 	 * Number of threads
 	 */
-	int num_threads;
+	unsigned num_threads;
 
 	/*
 	 * Number of idle threads
 	 */
-	int num_idle;
+	unsigned num_idle;
 
 	/*
 	 * Condition variable indicating that helper threads should
@@ -168,7 +176,8 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 		return ret;
 	}
 
-	pool->shutdown = false;
+	pool->stopped = false;
+	pool->destroyed = false;
 	pool->num_threads = 0;
 	pool->max_threads = max_threads;
 	pool->num_idle = 0;
@@ -195,6 +204,43 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 	return 0;
 }
 
+size_t pthreadpool_max_threads(struct pthreadpool *pool)
+{
+	if (pool->stopped) {
+		return 0;
+	}
+
+	return pool->max_threads;
+}
+
+size_t pthreadpool_queued_jobs(struct pthreadpool *pool)
+{
+	int res;
+	int unlock_res;
+	size_t ret;
+
+	if (pool->stopped) {
+		return 0;
+	}
+
+	res = pthread_mutex_lock(&pool->mutex);
+	if (res != 0) {
+		return res;
+	}
+
+	if (pool->stopped) {
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
+		return 0;
+	}
+
+	ret = pool->num_jobs;
+
+	unlock_res = pthread_mutex_unlock(&pool->mutex);
+	assert(unlock_res == 0);
+	return ret;
+}
+
 static void pthreadpool_prepare_pool(struct pthreadpool *pool)
 {
 	int ret;
@@ -206,7 +252,7 @@ static void pthreadpool_prepare_pool(struct pthreadpool *pool)
 	assert(ret == 0);
 
 	while (pool->num_idle != 0) {
-		int num_idle = pool->num_idle;
+		unsigned num_idle = pool->num_idle;
 		pthread_cond_t prefork_cond;
 
 		ret = pthread_cond_init(&prefork_cond, NULL);
@@ -328,6 +374,11 @@ static int pthreadpool_free(struct pthreadpool *pool)
 	ret = pthread_mutex_unlock(&pthreadpools_mutex);
 	assert(ret == 0);
 
+	ret = pthread_mutex_lock(&pool->mutex);
+	assert(ret == 0);
+	ret = pthread_mutex_unlock(&pool->mutex);
+	assert(ret == 0);
+
 	ret = pthread_mutex_destroy(&pool->mutex);
 	ret1 = pthread_cond_destroy(&pool->condvar);
 	ret2 = pthread_mutex_destroy(&pool->fork_mutex);
@@ -349,11 +400,33 @@ static int pthreadpool_free(struct pthreadpool *pool)
 }
 
 /*
- * Destroy a thread pool. Wake up all idle threads for exit. The last
- * one will free the pool.
+ * Stop a thread pool. Wake up all idle threads for exit.
  */
 
-int pthreadpool_destroy(struct pthreadpool *pool)
+static int pthreadpool_stop_locked(struct pthreadpool *pool)
+{
+	int ret;
+
+	pool->stopped = true;
+
+	if (pool->num_threads == 0) {
+		return 0;
+	}
+
+	/*
+	 * We have active threads, tell them to finish.
+	 */
+
+	ret = pthread_cond_broadcast(&pool->condvar);
+
+	return ret;
+}
+
+/*
+ * Stop a thread pool. Wake up all idle threads for exit.
+ */
+
+int pthreadpool_stop(struct pthreadpool *pool)
 {
 	int ret, ret1;
 
@@ -362,34 +435,50 @@ int pthreadpool_destroy(struct pthreadpool *pool)
 		return ret;
 	}
 
-	if (pool->shutdown) {
-		ret = pthread_mutex_unlock(&pool->mutex);
-		assert(ret == 0);
-		return EBUSY;
+	if (!pool->stopped) {
+		ret = pthreadpool_stop_locked(pool);
 	}
 
-	pool->shutdown = true;
+	ret1 = pthread_mutex_unlock(&pool->mutex);
+	assert(ret1 == 0);
 
-	if (pool->num_threads == 0) {
-		ret = pthread_mutex_unlock(&pool->mutex);
-		assert(ret == 0);
+	return ret;
+}
 
-		ret = pthreadpool_free(pool);
+/*
+ * Destroy a thread pool. Wake up all idle threads for exit. The last
+ * one will free the pool.
+ */
+
+int pthreadpool_destroy(struct pthreadpool *pool)
+{
+	int ret, ret1;
+	bool free_it;
+
+	assert(!pool->destroyed);
+
+	ret = pthread_mutex_lock(&pool->mutex);
+	if (ret != 0) {
 		return ret;
 	}
 
-	/*
-	 * We have active threads, tell them to finish.
-	 */
+	pool->destroyed = true;
 
-	ret = pthread_cond_broadcast(&pool->condvar);
+	if (!pool->stopped) {
+		ret = pthreadpool_stop_locked(pool);
+	}
+
+	free_it = (pool->num_threads == 0);
 
 	ret1 = pthread_mutex_unlock(&pool->mutex);
 	assert(ret1 == 0);
 
+	if (free_it) {
+		pthreadpool_free(pool);
+	}
+
 	return ret;
 }
-
 /*
  * Prepare for pthread_exit(), pool->mutex must be locked and will be
  * unlocked here. This is a bit of a layering violation, but here we
@@ -402,7 +491,7 @@ static void pthreadpool_server_exit(struct pthreadpool *pool)
 
 	pool->num_threads -= 1;
 
-	free_it = (pool->shutdown && (pool->num_threads == 0));
+	free_it = (pool->destroyed && (pool->num_threads == 0));
 
 	ret = pthread_mutex_unlock(&pool->mutex);
 	assert(ret == 0);
@@ -415,6 +504,10 @@ static void pthreadpool_server_exit(struct pthreadpool *pool)
 static bool pthreadpool_get_job(struct pthreadpool *p,
 				struct pthreadpool_job *job)
 {
+	if (p->stopped) {
+		return false;
+	}
+
 	if (p->num_jobs == 0) {
 		return false;
 	}
@@ -494,7 +587,7 @@ static void *pthreadpool_server(void *arg)
 		clock_gettime(CLOCK_REALTIME, &ts);
 		ts.tv_sec += 1;
 
-		while ((pool->num_jobs == 0) && !pool->shutdown) {
+		while ((pool->num_jobs == 0) && !pool->stopped) {
 
 			pool->num_idle += 1;
 			res = pthread_cond_timedwait(
@@ -572,10 +665,9 @@ static void *pthreadpool_server(void *arg)
 			}
 		}
 
-		if ((pool->num_jobs == 0) && pool->shutdown) {
+		if (pool->stopped) {
 			/*
-			 * No more work to do and we're asked to shut down, so
-			 * exit
+			 * we're asked to stop processing jobs, so exit
 			 */
 			pthreadpool_server_exit(pool);
 			return NULL;
@@ -632,33 +724,48 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 			void (*fn)(void *private_data), void *private_data)
 {
 	int res;
+	int unlock_res;
+
+	assert(!pool->destroyed);
 
 	res = pthread_mutex_lock(&pool->mutex);
 	if (res != 0) {
 		return res;
 	}
 
-	if (pool->shutdown) {
+	if (pool->stopped) {
 		/*
 		 * Protect against the pool being shut down while
 		 * trying to add a job
 		 */
-		res = pthread_mutex_unlock(&pool->mutex);
-		assert(res == 0);
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
 		return EINVAL;
 	}
 
+	if (pool->max_threads == 0) {
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
+
+		/*
+		 * If no thread are allowed we do strict sync processing.
+		 */
+		fn(private_data);
+		res = pool->signal_fn(job_id, fn, private_data,
+				      pool->signal_fn_private_data);
+		return res;
+	}
+
 	/*
 	 * Add job to the end of the queue
 	 */
 	if (!pthreadpool_put_job(pool, job_id, fn, private_data)) {
-		res = pthread_mutex_unlock(&pool->mutex);
-		assert(res == 0);
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
 		return ENOMEM;
 	}
 
 	if (pool->num_idle > 0) {
-		int unlock_res;
 		/*
 		 * We have idle threads, wake one.
 		 */
@@ -671,20 +778,19 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 		return res;
 	}
 
-	if ((pool->max_threads != 0) &&
-	    (pool->num_threads >= pool->max_threads)) {
+	if (pool->num_threads >= pool->max_threads) {
 		/*
 		 * No more new threads, we just queue the request
 		 */
-		res = pthread_mutex_unlock(&pool->mutex);
-		assert(res == 0);
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
 		return 0;
 	}
 
 	res = pthreadpool_create_thread(pool);
 	if (res == 0) {
-		res = pthread_mutex_unlock(&pool->mutex);
-		assert(res == 0);
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
 		return 0;
 	}
 
@@ -693,8 +799,8 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 		 * At least one thread is still available, let
 		 * that one run the queued job.
 		 */
-		res = pthread_mutex_unlock(&pool->mutex);
-		assert(res == 0);
+		unlock_res = pthread_mutex_unlock(&pool->mutex);
+		assert(unlock_res == 0);
 		return 0;
 	}
 
@@ -704,11 +810,56 @@ int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 	 */
 	pthreadpool_undo_put_job(pool);
 
+	unlock_res = pthread_mutex_unlock(&pool->mutex);
+	assert(unlock_res == 0);
+
+	return res;
+}
+
+size_t pthreadpool_cancel_job(struct pthreadpool *pool, int job_id,
+			      void (*fn)(void *private_data), void *private_data)
+{
+	int res;
+	size_t i, j;
+	size_t num = 0;
+
+	assert(!pool->destroyed);
+
+	res = pthread_mutex_lock(&pool->mutex);
+	if (res != 0) {
+		return res;
+	}
+
+	for (i = 0, j = 0; i < pool->num_jobs; i++) {
+		size_t idx = (pool->head + i) % pool->jobs_array_len;
+		size_t new_idx = (pool->head + j) % pool->jobs_array_len;
+		struct pthreadpool_job *job = &pool->jobs[idx];
+
+		if ((job->private_data == private_data) &&
+		    (job->id == job_id) &&
+		    (job->fn == fn))
+		{
+			/*
+			 * Just skip the entry.
+			 */
+			num++;
+			continue;
+		}
+
+		/*
+		 * If we already removed one or more jobs (so j will be smaller
+		 * then i), we need to fill possible gaps in the logical list.
+		 */
+		if (j < i) {
+			pool->jobs[new_idx] = *job;
+		}
+		j++;
+	}
+
+	pool->num_jobs -= num;
+
 	res = pthread_mutex_unlock(&pool->mutex);
 	assert(res == 0);
 
-	fn(private_data);
-	res = pool->signal_fn(job_id, fn, private_data,
-			      pool->signal_fn_private_data);
-	return res;
+	return num;
 }
diff --git a/lib/pthreadpool/pthreadpool.h b/lib/pthreadpool/pthreadpool.h
index defbe5a..b473358 100644
--- a/lib/pthreadpool/pthreadpool.h
+++ b/lib/pthreadpool/pthreadpool.h
@@ -51,8 +51,51 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
 		     void *signal_fn_private_data);
 
 /**
+ * @brief Get the max threads value of pthreadpool
+ *
+ * @note This can be 0 for strict sync processing.
+ *
+ * @param[in]	pool		The pool
+ * @return			number of possible threads
+ */
+size_t pthreadpool_max_threads(struct pthreadpool *pool);
+
+/**
+ * @brief The number of queued jobs of pthreadpool
+ *
+ * This is the number of jobs added by pthreadpool_add_job(),
+ * which are not yet processed by a thread.
+ *
+ * @param[in]	pool		The pool
+ * @return			The number of jobs
+ */
+size_t pthreadpool_queued_jobs(struct pthreadpool *pool);
+
+/**
+ * @brief Stop a pthreadpool
+ *
+ * Stop a pthreadpool. If jobs are submitted, but not yet active in
+ * a thread, they won't get executed. If a job has already been
+ * submitted to a thread, the job function will continue running, and
+ * the signal function might still be called.
+ *
+ * This allows a multi step shutdown using pthreadpool_stop(),
+ * pthreadpool_cancel_job() and pthreadpool_destroy().
+ *
+ * @param[in]	pool		The pool to stop
+ * @return			success: 0, failure: errno
+ *
+ * @see pthreadpool_cancel_job()
+ * @see pthreadpool_destroy()
+ */
+int pthreadpool_stop(struct pthreadpool *pool);
+
+/**
  * @brief Destroy a pthreadpool
  *
+ * This basically implies pthreadpool_stop() if the pool
+ * isn't already stopped.
+ *
  * Destroy a pthreadpool. If jobs are submitted, but not yet active in
  * a thread, they won't get executed. If a job has already been
  * submitted to a thread, the job function will continue running, and
@@ -63,6 +106,8 @@ int pthreadpool_init(unsigned max_threads, struct pthreadpool **presult,
  *
  * @param[in]	pool		The pool to destroy
  * @return			success: 0, failure: errno
+ *
+ * @see pthreadpool_stop()
  */
 int pthreadpool_destroy(struct pthreadpool *pool);
 
@@ -82,4 +127,32 @@ int pthreadpool_destroy(struct pthreadpool *pool);
 int pthreadpool_add_job(struct pthreadpool *pool, int job_id,
 			void (*fn)(void *private_data), void *private_data);
 
+/**
+ * @brief Try to cancel a job in a pthreadpool
+ *
+ * This tries to cancel a job in a pthreadpool. The same
+ * arguments, which were given to pthreadpool_add_job()
+ * needs to be passed.
+ *
+ * The combination of id, fn, private_data might not be unique.
+ * So the function tries to cancel as much matching jobs as possible.
+ * Note once a job is scheduled in a thread it's to late to
+ * cancel it.
+ *
+ * Canceled jobs that weren't started yet won't be reported via a
+ * pool's signal_fn.
+ *
+ * @param[in]	pool		The pool to run the job on
+ * @param[in]	job_id		A custom identifier


-- 
Samba Shared Repository



More information about the samba-cvs mailing list