libc_r & direct usage of syscalls

Alexey Zelkin phantom at
Thu Oct 23 02:35:04 PDT 2003


On Wed, Oct 22, 2003 at 10:06:10PM -0400, Daniel Eischen wrote:

> > Some of you may remember a story about strange problems I had
> > with native jdk14 and fork() calls.
> > 
> > In few words -- sometimes, in absolutely random order JVM just after
> > call to fork() function become unusable due to SIGBUS signal storm
> > (JVM signal handler decided that this signal is not fatal and did not
> > stop an application).
> > 
> > Today I have completely tracked it down.  Or correctly to say
> > got a 100% reproducible .java testcase and wrote few more .c testcases in
> > order to prove my point of view.
> > 
> > JVM is using internally usual stack protection logic.  Every two pages on
> > borders of stack are protected with mmap().  When something accesses
> > it SIGBUS is generated and signal handler forces overflowing thread
> > to rollback some operation until it may safely continue its job.
> > 
> > fork() is special case here.  When fork() is called, child process
> > is need to reinitialize a libc_r internal state (this job is done by
> > fork() wrapper located in libc_r/uthread/uthread_fork.c).  One of steps
> > of reinitialization process is free()'ing of pthreads stacks.  Caveat here
> > is unchanged protections on stack pages.  Right after some stacks are
> > free()'ed, malloc internal (struct pginfo *) info got allocated into
> > protected region and this info being changed we get a big *KABOOM* (i.e.
> > SIGBUS).
> Here's what POSIX has to say about fork() and threaded processes:
>   A process shall be created with a single thread. If a multi-threaded
>   process calls fork(), the new process shall contain a replica of the
>   calling thread and its entire address space, possibly including the
>   states of mutexes and other resources. Consequently, to avoid
>   errors, the child process may only execute async-signal-safe
>   operations until such time as one of the exec functions is called.
>   [THR]   Fork handlers may be established by means of the
>   pthread_atfork() function in order to maintain application
>   invariants across fork() calls. 
>   When the application calls fork() from a signal handler and any of
>   the fork handlers registered by pthread_atfork() calls a function
>   that is not asynch-signal-safe, the behavior is undefined.

>From quick look I was unable to find any entity named pthread_atfork()
in FreeBSD.  I also doubt it will help with my issue at all, because
most probabaly atfork functions will be executed at the end of pthread_fork(),
but my problem appears at the begining of the function.

> Libkse currently doesn't do any reinitialization of internal library
> state (libc _or_ libkse) on a fork().  You cannot rely on libc
> state (malloc state, e.g.) or libkse state after a fork().

Well.  I looked on fork() implementation in libkse and it looks safe for
my case.  Is there any standard way to detect which library I am running ?
I can do runtime check (using dl*() funcs) in order to understand which
library application running and execute different code paths.

> For what purpose is fork() being used by the JVM?

For spawning another process.  As I shown in code examples in previous letter
fork() is used to born another process, then close unused file descriptors
in child and then call execvp().

More information about the freebsd-threads mailing list