[PATCH] Fix pthreadpools with fork()
Volker Lendecke
Volker.Lendecke at SerNet.DE
Mon Mar 3 05:03:39 MST 2014
Hi!
Review would be appreciated.
Thanks,
Volker
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From 2fdb69cc1d341b769a049aa28d470a3966ab9476 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 3 Mar 2014 12:20:41 +0100
Subject: [PATCH 1/2] pthreadpool: Fix pthreadpools with fork
The current could would crash if a pthreadpool was created, deleted and the
process then fork()s. "pthreadpools" is NULL in this case, but the
pthread_atfork handlers are in place. This fixes walking the pthreadpools list
in reverse.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/lib/pthreadpool/pthreadpool.c | 21 ++++++---------------
1 file changed, 6 insertions(+), 15 deletions(-)
diff --git a/source3/lib/pthreadpool/pthreadpool.c b/source3/lib/pthreadpool/pthreadpool.c
index bd58d62..654d420 100644
--- a/source3/lib/pthreadpool/pthreadpool.c
+++ b/source3/lib/pthreadpool/pthreadpool.c
@@ -188,16 +188,11 @@ static void pthreadpool_parent(void)
int ret;
struct pthreadpool *pool;
- pool = DLIST_TAIL(pthreadpools);
-
- while (1) {
+ for (pool = DLIST_TAIL(pthreadpools);
+ pool != NULL;
+ pool = DLIST_PREV(pool)) {
ret = pthread_mutex_unlock(&pool->mutex);
assert(ret == 0);
-
- if (pool == pthreadpools) {
- break;
- }
- pool = pool->prev;
}
ret = pthread_mutex_unlock(&pthreadpools_mutex);
@@ -209,9 +204,10 @@ static void pthreadpool_child(void)
int ret;
struct pthreadpool *pool;
- pool = DLIST_TAIL(pthreadpools);
+ for (pool = DLIST_TAIL(pthreadpools);
+ pool != NULL;
+ pool = DLIST_PREV(pool)) {
- while (1) {
close(pool->sig_pipe[0]);
close(pool->sig_pipe[1]);
@@ -236,11 +232,6 @@ static void pthreadpool_child(void)
ret = pthread_mutex_unlock(&pool->mutex);
assert(ret == 0);
-
- if (pool == pthreadpools) {
- break;
- }
- pool = pool->prev;
}
ret = pthread_mutex_unlock(&pthreadpools_mutex);
--
1.8.1.2
From 4ed022997ea27391d83c4fc5ff88d35b452967cd Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Mon, 3 Mar 2014 11:57:18 +0000
Subject: [PATCH 2/2] pthreadpool: Add test for fork crash
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/lib/pthreadpool/tests.c | 48 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/source3/lib/pthreadpool/tests.c b/source3/lib/pthreadpool/tests.c
index 95d37b6..170cedf 100644
--- a/source3/lib/pthreadpool/tests.c
+++ b/source3/lib/pthreadpool/tests.c
@@ -5,6 +5,8 @@
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
#include "pthreadpool.h"
static int test_init(void)
@@ -318,6 +320,46 @@ static int test_threaded_addjob(int num_pools, int num_threads, int poolsize,
return 0;
}
+static int test_fork(void)
+{
+ struct pthreadpool *p;
+ pid_t child, waited;
+ int status, ret;
+
+ ret = pthreadpool_init(1, &p);
+ if (ret != 0) {
+ fprintf(stderr, "pthreadpool_init failed: %s\n",
+ strerror(ret));
+ return -1;
+ }
+ ret = pthreadpool_destroy(p);
+ if (ret != 0) {
+ fprintf(stderr, "pthreadpool_destroy failed: %s\n",
+ strerror(ret));
+ return -1;
+ }
+
+ child = fork();
+ if (child < 0) {
+ perror("fork failed");
+ return -1;
+ }
+ if (child == 0) {
+ exit(0);
+ }
+ waited = wait(&status);
+ if (waited == -1) {
+ perror("wait failed");
+ return -1;
+ }
+ if (waited != child) {
+ fprintf(stderr, "expected child %d, got %d\n",
+ (int)child, (int)waited);
+ return -1;
+ }
+ return 0;
+}
+
int main(void)
{
int ret;
@@ -328,6 +370,12 @@ int main(void)
return 1;
}
+ ret = test_fork();
+ if (ret != 0) {
+ fprintf(stderr, "test_fork failed\n");
+ return 1;
+ }
+
ret = test_jobs(10, 10000);
if (ret != 0) {
fprintf(stderr, "test_jobs failed\n");
--
1.8.1.2
More information about the samba-technical
mailing list