Re: threaded, forked, rethreaded processes will deadlock

2009-03-18 Thread David Xu

Kostik Belousov wrote:

I looked at the issue once more recently, and I propose the following
much less intrusive patch. It is somewhat hackish, but I think that
it would be good to have this working. Most other Unixes do have
working thread library after the fork. Any objections ?

diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c
index bc410d1..ae6b9ad 100644
--- a/lib/libthr/thread/thr_fork.c
+++ b/lib/libthr/thread/thr_fork.c
@@ -173,14 +173,19 @@ _fork(void)
 		/* Ready to continue, unblock signals. */ 
 		_thr_signal_unblock(curthread);
 
-		if (unlock_malloc)

+   if (unlock_malloc) {
+   __isthreaded = 1;
_malloc_postfork();
+   __isthreaded = 0;
+   }
 
 		/* Run down atfork child handlers. */

TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
if (af->child != NULL)
af->child();
}
+
+   THR_UMUTEX_UNLOCK(curthread, &_thr_atfork_lock);


^^^
This line is not needed.


} else {
/* Parent process */
errsave = errno;




___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-03-18 Thread Daniel Eischen

On Wed, 18 Mar 2009, Kostik Belousov wrote:


I looked at the issue once more recently, and I propose the following
much less intrusive patch. It is somewhat hackish, but I think that
it would be good to have this working. Most other Unixes do have
working thread library after the fork. Any objections ?


No objections.

--
DE
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-03-18 Thread Kostik Belousov
On Thu, Jan 22, 2009 at 12:42:56AM -0500, Daniel Eischen wrote:
> On Wed, 21 Jan 2009, David Schultz wrote:
> 
> >I think there *is* a real bug here, but there's two distinct ways
> >to fix it. When a threaded process forks, malloc acquires all its
> >locks so that its state is consistent after a fork. However, the
> >post-fork hook that's supposed to release these locks fails to do
> >so in the child because the child process isn't threaded, and
> >malloc_mutex_unlock() is optimized to be a no-op in
> >single-threaded processes. If the child *stays* single-threaded,
> >malloc() works by accident even with all the locks held because
> >malloc_mutex_lock() is also a no-op in single-threaded processes.
> >But if the child goes multi-threaded, then things break.
> >
> >Solution 1 is to actually unlock the locks in the child process,
> >which is what Brian is proposing.
> >
> >Solution 2 is to take the position that all of this pre- and
> >post-fork bloat in the fork() path is gratuitous and should be
> >removed. The rationale here is that if you fork with multiple
> >running threads, there's scads of ways in which the child's heap
> >could be inconsistent; fork hooks would be needed not just in
> >malloc(), but in stdio, third party libraries, etc. Why should
> >malloc() be special? It's the programmer's job to quiesce all the
> >threads before calling fork(), and if the programmer doesn't do
> >this, then POSIX only guarantees that async-signal-safe functions
> >will work.
> >
> >Note that Solution 2 also fixes Brian's problem if he quiesces all
> >of his worker threads before forking (as he should!) With the
> >pre-fork hook removed, all the locks will start out free in the
> >child.  So that's what I vote for...
> 
> The problem is that our own libraries (libthr included)
> need to malloc() for themselves, even after a fork() in
> the child.  After a fork(), the malloc locks should be
> reinitialized in the child if it was threaded, so that
> our implementation actually works for all the async
> signal calls, fork(), exec(), etc.  I forget the exact
> failure modes for very common cases, but if you remove
> the re-initialization of the malloc locks, I'm sure
> you will have problems.
> 
> Perhaps much of this malloc() stuff goes away when we
> move to pthread locks that are not pointers to allocated
> objects, but instead are actual objects/structures.
> This needs to be done in order for mutexes/CVs/etc
> to be PTHREAD_PROCESS_SHARED (placed in shared memory
> and used by multiple processes).  In other words,
> pthread_mutex_t goes from this:
> 
>   typedef struct pthread_mutex *pthread_mutex_t;
> 
> to something like this:
> 
>   struct __pthread_mutex {
>   uint32_tlock;
>   ...
>   }
>   typedef struct __pthread_mutex pthread_mutex_t;
> 
> Same thing for CVs, and we probably should convert any other
> locks used internally by libc/libpthread (spinlocks).
> 
> So after a fork(), there is no need to reallocate anything,
> it can just be reinitialized if necessary.
> 

I looked at the issue once more recently, and I propose the following
much less intrusive patch. It is somewhat hackish, but I think that
it would be good to have this working. Most other Unixes do have
working thread library after the fork. Any objections ?

diff --git a/lib/libthr/thread/thr_fork.c b/lib/libthr/thread/thr_fork.c
index bc410d1..ae6b9ad 100644
--- a/lib/libthr/thread/thr_fork.c
+++ b/lib/libthr/thread/thr_fork.c
@@ -173,14 +173,19 @@ _fork(void)
/* Ready to continue, unblock signals. */ 
_thr_signal_unblock(curthread);
 
-   if (unlock_malloc)
+   if (unlock_malloc) {
+   __isthreaded = 1;
_malloc_postfork();
+   __isthreaded = 0;
+   }
 
/* Run down atfork child handlers. */
TAILQ_FOREACH(af, &_thr_atfork_list, qe) {
if (af->child != NULL)
af->child();
}
+
+   THR_UMUTEX_UNLOCK(curthread, &_thr_atfork_lock);
} else {
/* Parent process */
errsave = errno;


pgplLb1p3doD4.pgp
Description: PGP signature


Re: threaded, forked, rethreaded processes will deadlock

2009-01-26 Thread Brian Fundakowski Feldman
On Thu, Jan 22, 2009 at 12:42:56AM -0500, Daniel Eischen wrote:
> On Wed, 21 Jan 2009, David Schultz wrote:
> 
>> I think there *is* a real bug here, but there's two distinct ways
>> to fix it. When a threaded process forks, malloc acquires all its
>> locks so that its state is consistent after a fork. However, the
>> post-fork hook that's supposed to release these locks fails to do
>> so in the child because the child process isn't threaded, and
>> malloc_mutex_unlock() is optimized to be a no-op in
>> single-threaded processes. If the child *stays* single-threaded,
>> malloc() works by accident even with all the locks held because
>> malloc_mutex_lock() is also a no-op in single-threaded processes.
>> But if the child goes multi-threaded, then things break.
>> 
>> Solution 1 is to actually unlock the locks in the child process,
>> which is what Brian is proposing.
>> 
>> Solution 2 is to take the position that all of this pre- and
>> post-fork bloat in the fork() path is gratuitous and should be
>> removed. The rationale here is that if you fork with multiple
>> running threads, there's scads of ways in which the child's heap
>> could be inconsistent; fork hooks would be needed not just in
>> malloc(), but in stdio, third party libraries, etc. Why should
>> malloc() be special? It's the programmer's job to quiesce all the
>> threads before calling fork(), and if the programmer doesn't do
>> this, then POSIX only guarantees that async-signal-safe functions
>> will work.
>> 
>> Note that Solution 2 also fixes Brian's problem if he quiesces all
>> of his worker threads before forking (as he should!) With the
>> pre-fork hook removed, all the locks will start out free in the
>> child.  So that's what I vote for...
> 
> The problem is that our own libraries (libthr included)
> need to malloc() for themselves, even after a fork() in
> the child.  After a fork(), the malloc locks should be
> reinitialized in the child if it was threaded, so that
> our implementation actually works for all the async
> signal calls, fork(), exec(), etc.  I forget the exact
> failure modes for very common cases, but if you remove
> the re-initialization of the malloc locks, I'm sure
> you will have problems.
> 
> Perhaps much of this malloc() stuff goes away when we
> move to pthread locks that are not pointers to allocated
> objects, but instead are actual objects/structures.
> This needs to be done in order for mutexes/CVs/etc
> to be PTHREAD_PROCESS_SHARED (placed in shared memory
> and used by multiple processes).  In other words,
> pthread_mutex_t goes from this:
> 
>   typedef struct pthread_mutex *pthread_mutex_t;
> 
> to something like this:
> 
>   struct __pthread_mutex {
>   uint32_tlock;
>   ...
>   }
>   typedef struct __pthread_mutex pthread_mutex_t;
> 
> Same thing for CVs, and we probably should convert any other
> locks used internally by libc/libpthread (spinlocks).
> 
> So after a fork(), there is no need to reallocate anything,
> it can just be reinitialized if necessary.

In this case it's not a matter of locks needing to be again initialized
-- the mutexes are fine -- they just need to be relinquished, which
never occurs for the child now, but used to work fine in 7.0.  What is
truly broken about the current behavior module the bug I'm trying to fix?

-- 
Brian Fundakowski Feldman   \'[ FreeBSD ]''\
  <> gr...@freebsd.org   \  The Power to Serve! \
 Opinions expressed are my own.   \,,\
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-21 Thread David Schultz
On Thu, Jan 22, 2009, David Schultz wrote:
> If you can't implement functions that are required to be
> async-signal-safe like fork() and exec() without malloc(), then
> for now I guess we should go for something along the lines of what
> Brian is proposing. If the app programmer has taken special pains
> to ensure that all other threads are stopped when a fork happens,
> the fork() call shouldn't return in the child with all the malloc
> locks bogusly held.

Note that even with Brian's patch, the memory associated with the
all the parent's threads' stacks is leaked, and libthr can't be
expected to be in a particularly happy state after all of its
threads disappear. It just happens to (sort of) work for now.

In any case, it's clearly a bug that libthr's fork handler calls
_malloc_postfork() in the child even when _malloc_postfork()
doesn't work properly in the (now single-threaded) child. Which
way to fix it is up to you guys...
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-21 Thread David Schultz
On Thu, Jan 22, 2009, Daniel Eischen wrote:
> On Wed, 21 Jan 2009, David Schultz wrote:
> 
> >I think there *is* a real bug here, but there's two distinct ways
> >to fix it. When a threaded process forks, malloc acquires all its
> >locks so that its state is consistent after a fork. However, the
> >post-fork hook that's supposed to release these locks fails to do
> >so in the child because the child process isn't threaded, and
> >malloc_mutex_unlock() is optimized to be a no-op in
> >single-threaded processes. If the child *stays* single-threaded,
> >malloc() works by accident even with all the locks held because
> >malloc_mutex_lock() is also a no-op in single-threaded processes.
> >But if the child goes multi-threaded, then things break.
> >
> >Solution 1 is to actually unlock the locks in the child process,
> >which is what Brian is proposing.
> >
> >Solution 2 is to take the position that all of this pre- and
> >post-fork bloat in the fork() path is gratuitous and should be
> >removed. The rationale here is that if you fork with multiple
> >running threads, there's scads of ways in which the child's heap
> >could be inconsistent; fork hooks would be needed not just in
> >malloc(), but in stdio, third party libraries, etc. Why should
> >malloc() be special? It's the programmer's job to quiesce all the
> >threads before calling fork(), and if the programmer doesn't do
> >this, then POSIX only guarantees that async-signal-safe functions
> >will work.
> >
> >Note that Solution 2 also fixes Brian's problem if he quiesces all
> >of his worker threads before forking (as he should!) With the
> >pre-fork hook removed, all the locks will start out free in the
> >child.  So that's what I vote for...
> 
> The problem is that our own libraries (libthr included)
> need to malloc() for themselves, even after a fork() in
> the child.  After a fork(), the malloc locks should be
> reinitialized in the child if it was threaded, so that
> our implementation actually works for all the async
> signal calls, fork(), exec(), etc.  I forget the exact
> failure modes for very common cases, but if you remove
> the re-initialization of the malloc locks, I'm sure
> you will have problems.

If you can't implement functions that are required to be
async-signal-safe like fork() and exec() without malloc(), then
for now I guess we should go for something along the lines of what
Brian is proposing. If the app programmer has taken special pains
to ensure that all other threads are stopped when a fork happens,
the fork() call shouldn't return in the child with all the malloc
locks bogusly held.
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-21 Thread Daniel Eischen

On Wed, 21 Jan 2009, David Schultz wrote:


I think there *is* a real bug here, but there's two distinct ways
to fix it. When a threaded process forks, malloc acquires all its
locks so that its state is consistent after a fork. However, the
post-fork hook that's supposed to release these locks fails to do
so in the child because the child process isn't threaded, and
malloc_mutex_unlock() is optimized to be a no-op in
single-threaded processes. If the child *stays* single-threaded,
malloc() works by accident even with all the locks held because
malloc_mutex_lock() is also a no-op in single-threaded processes.
But if the child goes multi-threaded, then things break.

Solution 1 is to actually unlock the locks in the child process,
which is what Brian is proposing.

Solution 2 is to take the position that all of this pre- and
post-fork bloat in the fork() path is gratuitous and should be
removed. The rationale here is that if you fork with multiple
running threads, there's scads of ways in which the child's heap
could be inconsistent; fork hooks would be needed not just in
malloc(), but in stdio, third party libraries, etc. Why should
malloc() be special? It's the programmer's job to quiesce all the
threads before calling fork(), and if the programmer doesn't do
this, then POSIX only guarantees that async-signal-safe functions
will work.

Note that Solution 2 also fixes Brian's problem if he quiesces all
of his worker threads before forking (as he should!) With the
pre-fork hook removed, all the locks will start out free in the
child.  So that's what I vote for...


The problem is that our own libraries (libthr included)
need to malloc() for themselves, even after a fork() in
the child.  After a fork(), the malloc locks should be
reinitialized in the child if it was threaded, so that
our implementation actually works for all the async
signal calls, fork(), exec(), etc.  I forget the exact
failure modes for very common cases, but if you remove
the re-initialization of the malloc locks, I'm sure
you will have problems.

Perhaps much of this malloc() stuff goes away when we
move to pthread locks that are not pointers to allocated
objects, but instead are actual objects/structures.
This needs to be done in order for mutexes/CVs/etc
to be PTHREAD_PROCESS_SHARED (placed in shared memory
and used by multiple processes).  In other words,
pthread_mutex_t goes from this:

typedef struct pthread_mutex *pthread_mutex_t;

to something like this:

struct __pthread_mutex {
uint32_tlock;
...
}
typedef struct __pthread_mutex pthread_mutex_t;

Same thing for CVs, and we probably should convert any other
locks used internally by libc/libpthread (spinlocks).

So after a fork(), there is no need to reallocate anything,
it can just be reinitialized if necessary.

--
DE
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-21 Thread David Schultz
I think there *is* a real bug here, but there's two distinct ways
to fix it. When a threaded process forks, malloc acquires all its
locks so that its state is consistent after a fork. However, the
post-fork hook that's supposed to release these locks fails to do
so in the child because the child process isn't threaded, and
malloc_mutex_unlock() is optimized to be a no-op in
single-threaded processes. If the child *stays* single-threaded,
malloc() works by accident even with all the locks held because
malloc_mutex_lock() is also a no-op in single-threaded processes.
But if the child goes multi-threaded, then things break.

Solution 1 is to actually unlock the locks in the child process,
which is what Brian is proposing.

Solution 2 is to take the position that all of this pre- and
post-fork bloat in the fork() path is gratuitous and should be
removed. The rationale here is that if you fork with multiple
running threads, there's scads of ways in which the child's heap
could be inconsistent; fork hooks would be needed not just in
malloc(), but in stdio, third party libraries, etc. Why should
malloc() be special? It's the programmer's job to quiesce all the
threads before calling fork(), and if the programmer doesn't do
this, then POSIX only guarantees that async-signal-safe functions
will work.

Note that Solution 2 also fixes Brian's problem if he quiesces all
of his worker threads before forking (as he should!) With the
pre-fork hook removed, all the locks will start out free in the
child.  So that's what I vote for...
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-21 Thread Daniel Eischen

On Wed, 21 Jan 2009, Brian Fundakowski Feldman wrote:


On Mon, Jan 19, 2009 at 07:41:35PM -0500, Brian Fundakowski Feldman wrote:

On Fri, Jan 16, 2009 at 02:36:06PM -0800, Jason Evans wrote:

Brian Fundakowski Feldman wrote:
> Could you, and anyone else who would care to, check this out?  It's a
regression

fix but it also makes the code a little bit clearer.  Thanks!

Index: lib/libc/stdlib/malloc.c


Why does malloc need to change for this?  Unless there's a really good
reason, I don't want the extra branches in the locking functions.


Because malloc is the thing causing the regression.  It is easy enough
to optimize out the one extra fetch and branch in the single-threaded case
if I can get some consensus that the fix to it is actually fine.


The changes to thr_fork.c seem gratuituous; they don't
affect any functionality, and I don't see the difference
between the flag saying "unlock the malloc mutex" or
"I was threaded".  Clearly, it is set in "if (__isthreaded)",
so it is obvious that it indeed was threaded.

I can't speak to the malloc changes...

--
DE
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-21 Thread Brian Fundakowski Feldman
On Mon, Jan 19, 2009 at 07:41:35PM -0500, Brian Fundakowski Feldman wrote:
> On Fri, Jan 16, 2009 at 02:36:06PM -0800, Jason Evans wrote:
> > Brian Fundakowski Feldman wrote:
> >  > Could you, and anyone else who would care to, check this out?  It's a 
> > regression
> >> fix but it also makes the code a little bit clearer.  Thanks!
> >> 
> >> Index: lib/libc/stdlib/malloc.c
> > 
> > Why does malloc need to change for this?  Unless there's a really good 
> > reason, I don't want the extra branches in the locking functions.
> 
> Because malloc is the thing causing the regression.  It is easy enough
> to optimize out the one extra fetch and branch in the single-threaded case
> if I can get some consensus that the fix to it is actually fine.

Pessimization removed:
Index: lib/libc/stdlib/malloc.c
===
--- lib/libc/stdlib/malloc.c(revision 187160)
+++ lib/libc/stdlib/malloc.c(working copy)
@@ -1217,6 +1217,13 @@
_SPINUNLOCK(&mutex->lock);
 }
 
+static inline void
+malloc_mutex_always_unlock(malloc_mutex_t *mutex)
+{
+
+   _SPINUNLOCK(&mutex->lock);
+}
+
 /*
  * End mutex.
  */
@@ -1300,6 +1307,13 @@
_pthread_mutex_unlock(lock);
 }
 
+static inline void
+malloc_spin_always_unlock(pthread_mutex_t *lock)
+{
+
+   _pthread_mutex_unlock(lock);
+}
+
 /*
  * End spin lock.
  */
@@ -5515,9 +5529,8 @@
 void
 _malloc_prefork(void)
 {
+   arena_t *larenas[narenas];
bool again;
-   unsigned i, j;
-   arena_t *larenas[narenas], *tarenas[narenas];
 
/* Acquire all mutexes in a safe order. */
 
@@ -5530,19 +5543,23 @@
 */
memset(larenas, 0, sizeof(arena_t *) * narenas);
do {
+   unsigned int i;
+
again = false;
 
malloc_spin_lock(&arenas_lock);
for (i = 0; i < narenas; i++) {
if (arenas[i] != larenas[i]) {
+   arena_t *tarenas[narenas];
+   unsigned int j;
+
memcpy(tarenas, arenas, sizeof(arena_t *) *
narenas);
malloc_spin_unlock(&arenas_lock);
for (j = 0; j < narenas; j++) {
if (larenas[j] != tarenas[j]) {
larenas[j] = tarenas[j];
-   malloc_spin_lock(
-   &larenas[j]->lock);
+   
malloc_spin_lock(&larenas[j]->lock);
}
}
again = true;
@@ -5569,19 +5586,24 @@
/* Release all mutexes, now that fork() has completed. */
 
 #ifdef MALLOC_DSS
-   malloc_mutex_unlock(&dss_mtx);
+   malloc_mutex_always_unlock(&dss_mtx);
 #endif
 
-   malloc_mutex_unlock(&huge_mtx);
+   malloc_mutex_always_unlock(&huge_mtx);
 
-   malloc_mutex_unlock(&base_mtx);
+   malloc_mutex_always_unlock(&base_mtx);
 
memcpy(larenas, arenas, sizeof(arena_t *) * narenas);
-   malloc_spin_unlock(&arenas_lock);
+   malloc_spin_always_unlock(&arenas_lock);
for (i = 0; i < narenas; i++) {
if (larenas[i] != NULL)
-   malloc_spin_unlock(&larenas[i]->lock);
+   malloc_spin_always_unlock(&larenas[i]->lock);
}
+   /*
+* This ends the special post-__isthreaded exemption behavior for
+* malloc stuff.  We should really be single threaded right now
+* in effect regardless of __isthreaded status.
+*/
 }
 
 /*
Index: lib/libthr/thread/thr_fork.c
===
--- lib/libthr/thread/thr_fork.c(revision 187160)
+++ lib/libthr/thread/thr_fork.c(working copy)
@@ -105,7 +105,7 @@
struct pthread_atfork *af;
pid_t ret;
int errsave;
-   int unlock_malloc;
+   int was_threaded;
int rtld_locks[MAX_RTLD_LOCKS];
 
if (!_thr_is_inited())
@@ -122,16 +122,16 @@
}
 
/*
-* Try our best to protect memory from being corrupted in
-* child process because another thread in malloc code will
-* simply be kill by fork().
+* All bets are off as to what should happen soon if the parent
+* process was not so kindly as to set up pthread fork hooks to
+* relinquish all running threads.
 */
if (_thr_isthreaded() != 0) {
-   unlock_malloc = 1;
+   was_threaded = 1;
_malloc_prefork();
_rtld_atfork_pre(rtld_locks);
} else {
-   unlock_malloc = 0;
+   was_threaded = 0;
}
 
/*
@@ -159,7 +159,7 @@
   

Re: threaded, forked, rethreaded processes will deadlock

2009-01-19 Thread Brian Fundakowski Feldman
On Fri, Jan 16, 2009 at 02:36:06PM -0800, Jason Evans wrote:
> Brian Fundakowski Feldman wrote:
>  > Could you, and anyone else who would care to, check this out?  It's a 
> regression
>> fix but it also makes the code a little bit clearer.  Thanks!
>> 
>> Index: lib/libc/stdlib/malloc.c
> 
> Why does malloc need to change for this?  Unless there's a really good 
> reason, I don't want the extra branches in the locking functions.

Because malloc is the thing causing the regression.  It is easy enough
to optimize out the one extra fetch and branch in the single-threaded case
if I can get some consensus that the fix to it is actually fine.

-- 
Brian Fundakowski Feldman   \'[ FreeBSD ]''\
  <> gr...@freebsd.org   \  The Power to Serve! \
 Opinions expressed are my own.   \,,\
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-16 Thread Jason Evans

Brian Fundakowski Feldman wrote:
 > Could you, and anyone else who would care to, check this out?  It's 
a regression

fix but it also makes the code a little bit clearer.  Thanks!

Index: lib/libc/stdlib/malloc.c


Why does malloc need to change for this?  Unless there's a really good 
reason, I don't want the extra branches in the locking functions.


Thanks,
Jason
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-16 Thread Brian Fundakowski Feldman
On Fri, Jan 09, 2009 at 09:39:08AM -0800, Julian Elischer wrote:
> Brian Fundakowski Feldman wrote:
>> On Thu, Jan 08, 2009 at 11:09:16PM -0800, Julian Elischer wrote:
>>> Brian Fundakowski Feldman wrote:
 On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:
> On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:
> 
>> It appears that the post-fork hooks for malloc(3) are somewhat broken 
>> such that
>> when a threaded program forks, and then its child attempts to go 
>> threaded, it
>> deadlocks because it already appears to have locks held.  I am not 
>> familiar
>> enough with the current libthr/libc/rtld-elf interaction that I've been 
>> able
>> to fix it myself, unfortunately.
> There's really nothing to fix - according to POSIX you are only
> allowed to call async-signal-safe functions in the child forked
> from a threaded process.  If you are trying to do anything other
> than that, it may or may not work on FreeBSD, but it is not
> guaranteed and is not portable.
> 
> The rationale is that what is the point of forking and creating
> more threads, when you can just as easily create more threads in
> the parent without forking?  The only reason to fork from a threaded
> process is to call one of the exec() functions.
 Well, it worked until the last major set of changes to malloc.  For me, 
 the point
 was that I was able to have transparent background worker threads in any 
 program
 regardless of its architecture, using the standard pthread fork hooks.  
 Could you
 point me to the POSIX section covering fork and threads?  If it's really 
 not
 supposed to work then that's fine, but there's an awful lot of code there 
 dedicated
 to support going threaded again after a fork.
 
>>> Practically, you can't go threaded again after a fork
>>> (by which I mean creating new threads or use things
>>> like mutexes etc.) in any posix system I know of.
>>> 
>>> It would require that:
>>>  The forking thread stop until:
>>>   Every other thread has released every resource it owns
>>>   and reports itself to be in a "safe quiescent state",
>>>   or at least report every resource it owns, especially
>>>   locks,
>>>  and
>>>  After the fork:
>>>   The child, post fork, to take ownership of all
>>>   of them, and free them.
>>> 
>>> You might be able to do that in a simple
>>> threaded program, but consider then that the libraries may have
>>> threads running in them of which you are unaware, and that
>>> some of the resources may interract with resources owned by the
>>> forking thread.
>>> 
>>> Add to this that there may be a signal thrown into this mix as well
>>> 
>>> (signals are the bane of thread developement)
>> 
>> Well, I wouldn't mind showing all of you what I can of what I had been doing
>> with the background threads -- it works pretty well modulo this particular
>> malloc lock bug.  Due to it being inappropriate to share library resources
>> between a child and parent for an open socket connection, I always considered
>> the only "safe" behavior to be going single-threaded for the duration of the 
>> fork
>> processes in both the parent and child, and the pthread_atfork(3) hooks have 
>> been
>> sufficient to do so.
> 
> 
> a
> well going single threaded for the duration of the fork, changes 
> everything!

Could you, and anyone else who would care to, check this out?  It's a regression
fix but it also makes the code a little bit clearer.  Thanks!

Index: lib/libc/stdlib/malloc.c
===
--- lib/libc/stdlib/malloc.c(revision 187160)
+++ lib/libc/stdlib/malloc.c(working copy)
@@ -415,6 +415,7 @@
 
 /* Set to true once the allocator has been initialized. */
 static bool malloc_initialized = false;
+static bool malloc_during_fork = false;
 
 /* Used to avoid initialization races. */
 static malloc_mutex_t init_lock = {_SPINLOCK_INITIALIZER};
@@ -1205,7 +1206,7 @@
 malloc_mutex_lock(malloc_mutex_t *mutex)
 {
 
-   if (__isthreaded)
+   if (__isthreaded || malloc_during_fork)
_SPINLOCK(&mutex->lock);
 }
 
@@ -1213,7 +1214,7 @@
 malloc_mutex_unlock(malloc_mutex_t *mutex)
 {
 
-   if (__isthreaded)
+   if (__isthreaded || malloc_during_fork)
_SPINUNLOCK(&mutex->lock);
 }
 
@@ -1260,7 +1261,7 @@
 {
unsigned ret = 0;
 
-   if (__isthreaded) {
+   if (__isthreaded || malloc_during_fork) {
if (_pthread_mutex_trylock(lock) != 0) {
/* Exponentially back off if there are multiple CPUs. */
if (ncpus > 1) {
@@ -1296,7 +1297,7 @@
 malloc_spin_unlock(pthread_mutex_t *lock)
 {
 
-   if (__isthreaded)
+   if (__isthreaded || malloc_during_fork)
_pthread_mutex_unlock(lock);
 }
 
@@ -5515,9 +5516,8 @@
 void
 _malloc_prefork(void)
 {
+   arena_t *larenas

Re: threaded, forked, rethreaded processes will deadlock

2009-01-09 Thread Brian Fundakowski Feldman
On Fri, Jan 09, 2009 at 07:42:32PM +0200, Kostik Belousov wrote:
> On Fri, Jan 09, 2009 at 11:34:26AM -0500, Brian Fundakowski Feldman wrote:
> > On Thu, Jan 08, 2009 at 11:09:16PM -0800, Julian Elischer wrote:
> > > Brian Fundakowski Feldman wrote:
> > >> On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:
> > >>> On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:
> > >>> 
> >  It appears that the post-fork hooks for malloc(3) are somewhat broken 
> >  such that
> >  when a threaded program forks, and then its child attempts to go 
> >  threaded, it
> >  deadlocks because it already appears to have locks held.  I am not 
> >  familiar
> >  enough with the current libthr/libc/rtld-elf interaction that I've 
> >  been able
> >  to fix it myself, unfortunately.
> > >>> There's really nothing to fix - according to POSIX you are only
> > >>> allowed to call async-signal-safe functions in the child forked
> > >>> from a threaded process.  If you are trying to do anything other
> > >>> than that, it may or may not work on FreeBSD, but it is not
> > >>> guaranteed and is not portable.
> > >>> 
> > >>> The rationale is that what is the point of forking and creating
> > >>> more threads, when you can just as easily create more threads in
> > >>> the parent without forking?  The only reason to fork from a threaded
> > >>> process is to call one of the exec() functions.
> > >> 
> > >> Well, it worked until the last major set of changes to malloc.  For me, 
> > >> the point
> > >> was that I was able to have transparent background worker threads in any 
> > >> program
> > >> regardless of its architecture, using the standard pthread fork hooks.  
> > >> Could you
> > >> point me to the POSIX section covering fork and threads?  If it's really 
> > >> not
> > >> supposed to work then that's fine, but there's an awful lot of code 
> > >> there dedicated
> > >> to support going threaded again after a fork.
> > >> 
> > > 
> > > Practically, you can't go threaded again after a fork
> > > (by which I mean creating new threads or use things
> > > like mutexes etc.) in any posix system I know of.
> > > 
> > > It would require that:
> > >  The forking thread stop until:
> > >   Every other thread has released every resource it owns
> > >   and reports itself to be in a "safe quiescent state",
> > >   or at least report every resource it owns, especially
> > >   locks,
> > >  and
> > >  After the fork:
> > >   The child, post fork, to take ownership of all
> > >   of them, and free them.
> > > 
> > > You might be able to do that in a simple
> > > threaded program, but consider then that the libraries may have
> > > threads running in them of which you are unaware, and that
> > > some of the resources may interract with resources owned by the
> > > forking thread.
> > > 
> > > Add to this that there may be a signal thrown into this mix as well
> > > 
> > > (signals are the bane of thread developement)
> > 
> > Well, I wouldn't mind showing all of you what I can of what I had been doing
> > with the background threads -- it works pretty well modulo this particular
> > malloc lock bug.  Due to it being inappropriate to share library resources
> > between a child and parent for an open socket connection, I always 
> > considered
> > the only "safe" behavior to be going single-threaded for the duration of 
> > the fork
> > processes in both the parent and child, and the pthread_atfork(3) hooks 
> > have been
> > sufficient to do so.
> > 
> In fact, try recent HEAD, it contains the fixed for deadlocks caused by
> fork calls in mt processes. Also, see r185456, that may be directly
> relevant to your problem.
> 
> The MFC to the stable/7 is doable, but depends on the MFC of some stuff
> committed by David Xu, that would take me some time to look into.

Ah, thank you for the pointer.  Seems this is an opportunity for me to catch up 
with
our switch to SVN, then.  I'll take a further look at this this weekend.  For 
reference,
these platforms passed the particular regression test I posted:
Linux 2.6.18-92.1.17.el5
SunOS 5.10 Generic_137138-09
Darwin macintosh.green.homeunix.org 9.6.0 Darwin Kernel Version 9.6.0: Mon Nov 
24 17:37:00 PST 2008;root:xnu-1228.9.59~1/RELEASE_I386 i386
FreeBSD 7.0-RELEASE
-- 
Brian Fundakowski Feldman   \'[ FreeBSD ]''\
  <> gr...@freebsd.org   \  The Power to Serve! \
 Opinions expressed are my own.   \,,\
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-09 Thread Kostik Belousov
On Fri, Jan 09, 2009 at 11:34:26AM -0500, Brian Fundakowski Feldman wrote:
> On Thu, Jan 08, 2009 at 11:09:16PM -0800, Julian Elischer wrote:
> > Brian Fundakowski Feldman wrote:
> >> On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:
> >>> On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:
> >>> 
>  It appears that the post-fork hooks for malloc(3) are somewhat broken 
>  such that
>  when a threaded program forks, and then its child attempts to go 
>  threaded, it
>  deadlocks because it already appears to have locks held.  I am not 
>  familiar
>  enough with the current libthr/libc/rtld-elf interaction that I've been 
>  able
>  to fix it myself, unfortunately.
> >>> There's really nothing to fix - according to POSIX you are only
> >>> allowed to call async-signal-safe functions in the child forked
> >>> from a threaded process.  If you are trying to do anything other
> >>> than that, it may or may not work on FreeBSD, but it is not
> >>> guaranteed and is not portable.
> >>> 
> >>> The rationale is that what is the point of forking and creating
> >>> more threads, when you can just as easily create more threads in
> >>> the parent without forking?  The only reason to fork from a threaded
> >>> process is to call one of the exec() functions.
> >> 
> >> Well, it worked until the last major set of changes to malloc.  For me, 
> >> the point
> >> was that I was able to have transparent background worker threads in any 
> >> program
> >> regardless of its architecture, using the standard pthread fork hooks.  
> >> Could you
> >> point me to the POSIX section covering fork and threads?  If it's really 
> >> not
> >> supposed to work then that's fine, but there's an awful lot of code there 
> >> dedicated
> >> to support going threaded again after a fork.
> >> 
> > 
> > Practically, you can't go threaded again after a fork
> > (by which I mean creating new threads or use things
> > like mutexes etc.) in any posix system I know of.
> > 
> > It would require that:
> >  The forking thread stop until:
> >   Every other thread has released every resource it owns
> >   and reports itself to be in a "safe quiescent state",
> >   or at least report every resource it owns, especially
> >   locks,
> >  and
> >  After the fork:
> >   The child, post fork, to take ownership of all
> >   of them, and free them.
> > 
> > You might be able to do that in a simple
> > threaded program, but consider then that the libraries may have
> > threads running in them of which you are unaware, and that
> > some of the resources may interract with resources owned by the
> > forking thread.
> > 
> > Add to this that there may be a signal thrown into this mix as well
> > 
> > (signals are the bane of thread developement)
> 
> Well, I wouldn't mind showing all of you what I can of what I had been doing
> with the background threads -- it works pretty well modulo this particular
> malloc lock bug.  Due to it being inappropriate to share library resources
> between a child and parent for an open socket connection, I always considered
> the only "safe" behavior to be going single-threaded for the duration of the 
> fork
> processes in both the parent and child, and the pthread_atfork(3) hooks have 
> been
> sufficient to do so.
> 
In fact, try recent HEAD, it contains the fixed for deadlocks caused by
fork calls in mt processes. Also, see r185456, that may be directly
relevant to your problem.

The MFC to the stable/7 is doable, but depends on the MFC of some stuff
committed by David Xu, that would take me some time to look into.


pgpzFbJ3BCzH2.pgp
Description: PGP signature


Re: threaded, forked, rethreaded processes will deadlock

2009-01-09 Thread Julian Elischer

Brian Fundakowski Feldman wrote:

On Thu, Jan 08, 2009 at 11:09:16PM -0800, Julian Elischer wrote:

Brian Fundakowski Feldman wrote:

On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:

On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:


It appears that the post-fork hooks for malloc(3) are somewhat broken such that
when a threaded program forks, and then its child attempts to go threaded, it
deadlocks because it already appears to have locks held.  I am not familiar
enough with the current libthr/libc/rtld-elf interaction that I've been able
to fix it myself, unfortunately.

There's really nothing to fix - according to POSIX you are only
allowed to call async-signal-safe functions in the child forked
from a threaded process.  If you are trying to do anything other
than that, it may or may not work on FreeBSD, but it is not
guaranteed and is not portable.

The rationale is that what is the point of forking and creating
more threads, when you can just as easily create more threads in
the parent without forking?  The only reason to fork from a threaded
process is to call one of the exec() functions.

Well, it worked until the last major set of changes to malloc.  For me, the 
point
was that I was able to have transparent background worker threads in any program
regardless of its architecture, using the standard pthread fork hooks.  Could 
you
point me to the POSIX section covering fork and threads?  If it's really not
supposed to work then that's fine, but there's an awful lot of code there 
dedicated
to support going threaded again after a fork.


Practically, you can't go threaded again after a fork
(by which I mean creating new threads or use things
like mutexes etc.) in any posix system I know of.

It would require that:
 The forking thread stop until:
  Every other thread has released every resource it owns
  and reports itself to be in a "safe quiescent state",
  or at least report every resource it owns, especially
  locks,
 and
 After the fork:
  The child, post fork, to take ownership of all
  of them, and free them.

You might be able to do that in a simple
threaded program, but consider then that the libraries may have
threads running in them of which you are unaware, and that
some of the resources may interract with resources owned by the
forking thread.

Add to this that there may be a signal thrown into this mix as well

(signals are the bane of thread developement)


Well, I wouldn't mind showing all of you what I can of what I had been doing
with the background threads -- it works pretty well modulo this particular
malloc lock bug.  Due to it being inappropriate to share library resources
between a child and parent for an open socket connection, I always considered
the only "safe" behavior to be going single-threaded for the duration of the 
fork
processes in both the parent and child, and the pthread_atfork(3) hooks have 
been
sufficient to do so.



a
well going single threaded for the duration of the fork, changes 
everything!






___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-09 Thread Brian Fundakowski Feldman
On Thu, Jan 08, 2009 at 11:09:16PM -0800, Julian Elischer wrote:
> Brian Fundakowski Feldman wrote:
>> On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:
>>> On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:
>>> 
 It appears that the post-fork hooks for malloc(3) are somewhat broken such 
 that
 when a threaded program forks, and then its child attempts to go threaded, 
 it
 deadlocks because it already appears to have locks held.  I am not familiar
 enough with the current libthr/libc/rtld-elf interaction that I've been 
 able
 to fix it myself, unfortunately.
>>> There's really nothing to fix - according to POSIX you are only
>>> allowed to call async-signal-safe functions in the child forked
>>> from a threaded process.  If you are trying to do anything other
>>> than that, it may or may not work on FreeBSD, but it is not
>>> guaranteed and is not portable.
>>> 
>>> The rationale is that what is the point of forking and creating
>>> more threads, when you can just as easily create more threads in
>>> the parent without forking?  The only reason to fork from a threaded
>>> process is to call one of the exec() functions.
>> 
>> Well, it worked until the last major set of changes to malloc.  For me, the 
>> point
>> was that I was able to have transparent background worker threads in any 
>> program
>> regardless of its architecture, using the standard pthread fork hooks.  
>> Could you
>> point me to the POSIX section covering fork and threads?  If it's really not
>> supposed to work then that's fine, but there's an awful lot of code there 
>> dedicated
>> to support going threaded again after a fork.
>> 
> 
> Practically, you can't go threaded again after a fork
> (by which I mean creating new threads or use things
> like mutexes etc.) in any posix system I know of.
> 
> It would require that:
>  The forking thread stop until:
>   Every other thread has released every resource it owns
>   and reports itself to be in a "safe quiescent state",
>   or at least report every resource it owns, especially
>   locks,
>  and
>  After the fork:
>   The child, post fork, to take ownership of all
>   of them, and free them.
> 
> You might be able to do that in a simple
> threaded program, but consider then that the libraries may have
> threads running in them of which you are unaware, and that
> some of the resources may interract with resources owned by the
> forking thread.
> 
> Add to this that there may be a signal thrown into this mix as well
> 
> (signals are the bane of thread developement)

Well, I wouldn't mind showing all of you what I can of what I had been doing
with the background threads -- it works pretty well modulo this particular
malloc lock bug.  Due to it being inappropriate to share library resources
between a child and parent for an open socket connection, I always considered
the only "safe" behavior to be going single-threaded for the duration of the 
fork
processes in both the parent and child, and the pthread_atfork(3) hooks have 
been
sufficient to do so.

-- 
Brian Fundakowski Feldman   \'[ FreeBSD ]''\
  <> gr...@freebsd.org   \  The Power to Serve! \
 Opinions expressed are my own.   \,,\
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-09 Thread Daniel Eischen

On Fri, 9 Jan 2009, Brian Fundakowski Feldman wrote:


On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:

On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:


It appears that the post-fork hooks for malloc(3) are somewhat broken such that
when a threaded program forks, and then its child attempts to go threaded, it
deadlocks because it already appears to have locks held.  I am not familiar
enough with the current libthr/libc/rtld-elf interaction that I've been able
to fix it myself, unfortunately.


There's really nothing to fix - according to POSIX you are only
allowed to call async-signal-safe functions in the child forked
from a threaded process.  If you are trying to do anything other
than that, it may or may not work on FreeBSD, but it is not
guaranteed and is not portable.

The rationale is that what is the point of forking and creating
more threads, when you can just as easily create more threads in
the parent without forking?  The only reason to fork from a threaded
process is to call one of the exec() functions.


Well, it worked until the last major set of changes to malloc.  For me, the 
point
was that I was able to have transparent background worker threads in any program
regardless of its architecture, using the standard pthread fork hooks.  Could 
you
point me to the POSIX section covering fork and threads?  If it's really not
supposed to work then that's fine, but there's an awful lot of code there 
dedicated
to support going threaded again after a fork.


I don't know if this link will work for you, but you can
start here:

  http://www.opengroup.org/onlinepubs/009695399/nframe.html

  "It is suggested that programs that use fork() call an exec
   function very soon afterwards in the child process, thus
   resetting all states. In the meantime, only a short list of
   async-signal-safe library routines are promised to be available."


-- DE
--
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-08 Thread Julian Elischer

Brian Fundakowski Feldman wrote:

On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:

On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:


It appears that the post-fork hooks for malloc(3) are somewhat broken such that
when a threaded program forks, and then its child attempts to go threaded, it
deadlocks because it already appears to have locks held.  I am not familiar
enough with the current libthr/libc/rtld-elf interaction that I've been able
to fix it myself, unfortunately.

There's really nothing to fix - according to POSIX you are only
allowed to call async-signal-safe functions in the child forked
from a threaded process.  If you are trying to do anything other
than that, it may or may not work on FreeBSD, but it is not
guaranteed and is not portable.

The rationale is that what is the point of forking and creating
more threads, when you can just as easily create more threads in
the parent without forking?  The only reason to fork from a threaded
process is to call one of the exec() functions.


Well, it worked until the last major set of changes to malloc.  For me, the 
point
was that I was able to have transparent background worker threads in any program
regardless of its architecture, using the standard pthread fork hooks.  Could 
you
point me to the POSIX section covering fork and threads?  If it's really not
supposed to work then that's fine, but there's an awful lot of code there 
dedicated
to support going threaded again after a fork.



Practically, you can't go threaded again after a fork
(by which I mean creating new threads or use things
like mutexes etc.) in any posix system I know of.

It would require that:
 The forking thread stop until:
  Every other thread has released every resource it owns
  and reports itself to be in a "safe quiescent state",
  or at least report every resource it owns, especially
  locks,
 and
 After the fork:
  The child, post fork, to take ownership of all
  of them, and free them.

You might be able to do that in a simple
threaded program, but consider then that the libraries may have
threads running in them of which you are unaware, and that
some of the resources may interract with resources owned by the
forking thread.

Add to this that there may be a signal thrown into this mix as well

(signals are the bane of thread developement)




___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-08 Thread Tim Kientzle

Brian Fundakowski Feldman wrote:

On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:

On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:


It appears that the post-fork hooks for malloc(3) are somewhat broken such that
when a threaded program forks, and then its child attempts to go threaded, it
deadlocks because it already appears to have locks held.  I am not familiar
enough with the current libthr/libc/rtld-elf interaction that I've been able
to fix it myself, unfortunately.


What version of FreeBSD?  I've only glanced through the
relevant code, but the malloc() implementation in -CURRENT
certainly tries to claim all malloc locks before the fork
and releases them all (in both child and parent) just
after the fork, so the scenario you describe shouldn't happen.

Of course, there may be other locks getting in the way.

Tim
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-08 Thread Brian Fundakowski Feldman
On Thu, Jan 08, 2009 at 10:44:20PM -0500, Daniel Eischen wrote:
> On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:
> 
>> It appears that the post-fork hooks for malloc(3) are somewhat broken such 
>> that
>> when a threaded program forks, and then its child attempts to go threaded, it
>> deadlocks because it already appears to have locks held.  I am not familiar
>> enough with the current libthr/libc/rtld-elf interaction that I've been able
>> to fix it myself, unfortunately.
> 
> There's really nothing to fix - according to POSIX you are only
> allowed to call async-signal-safe functions in the child forked
> from a threaded process.  If you are trying to do anything other
> than that, it may or may not work on FreeBSD, but it is not
> guaranteed and is not portable.
> 
> The rationale is that what is the point of forking and creating
> more threads, when you can just as easily create more threads in
> the parent without forking?  The only reason to fork from a threaded
> process is to call one of the exec() functions.

Well, it worked until the last major set of changes to malloc.  For me, the 
point
was that I was able to have transparent background worker threads in any program
regardless of its architecture, using the standard pthread fork hooks.  Could 
you
point me to the POSIX section covering fork and threads?  If it's really not
supposed to work then that's fine, but there's an awful lot of code there 
dedicated
to support going threaded again after a fork.

-- 
Brian Fundakowski Feldman   \'[ FreeBSD ]''\
  <> gr...@freebsd.org   \  The Power to Serve! \
 Opinions expressed are my own.   \,,\
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-08 Thread Dan Nelson
In the last episode (Jan 08), Daniel Eischen said:
> On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:
> > It appears that the post-fork hooks for malloc(3) are somewhat
> > broken such that when a threaded program forks, and then its child
> > attempts to go threaded, it deadlocks because it already appears to
> > have locks held.  I am not familiar enough with the current
> > libthr/libc/rtld-elf interaction that I've been able to fix it
> > myself, unfortunately.
> 
> There's really nothing to fix - according to POSIX you are only
> allowed to call async-signal-safe functions in the child forked from
> a threaded process.  If you are trying to do anything other than
> that, it may or may not work on FreeBSD, but it is not guaranteed and
> is not portable.

The Rationale section of the pthread_atfork() page is a good read here,
too.

-- 
Dan Nelson
dnel...@allantgroup.com
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"


Re: threaded, forked, rethreaded processes will deadlock

2009-01-08 Thread Daniel Eischen

On Thu, 8 Jan 2009, Brian Fundakowski Feldman wrote:


It appears that the post-fork hooks for malloc(3) are somewhat broken such that
when a threaded program forks, and then its child attempts to go threaded, it
deadlocks because it already appears to have locks held.  I am not familiar
enough with the current libthr/libc/rtld-elf interaction that I've been able
to fix it myself, unfortunately.


There's really nothing to fix - according to POSIX you are only
allowed to call async-signal-safe functions in the child forked
from a threaded process.  If you are trying to do anything other
than that, it may or may not work on FreeBSD, but it is not
guaranteed and is not portable.

The rationale is that what is the point of forking and creating
more threads, when you can just as easily create more threads in
the parent without forking?  The only reason to fork from a threaded
process is to call one of the exec() functions.

--
DE___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"

threaded, forked, rethreaded processes will deadlock

2009-01-08 Thread Brian Fundakowski Feldman
It appears that the post-fork hooks for malloc(3) are somewhat broken such that
when a threaded program forks, and then its child attempts to go threaded, it
deadlocks because it already appears to have locks held.  I am not familiar
enough with the current libthr/libc/rtld-elf interaction that I've been able
to fix it myself, unfortunately.

I discovered this today upgrading my work box from 7.0 to 7.1, but I can easily
reproduce it at home on a stale -CURRENT as well.  Testing on an OS X box to 
make
sure, the regression test does exit 0 there.

Has anyone happened to have fixed this already locally?

-- 
Brian Fundakowski Feldman   \'[ FreeBSD ]''\
  <> gr...@freebsd.org   \  The Power to Serve! \
 Opinions expressed are my own.   \,,\
___
freebsd-hackers@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "freebsd-hackers-unsubscr...@freebsd.org"