libc_r & direct usage of syscalls

Daniel Eischen eischen at vigrid.com
Wed Oct 22 19:06:13 PDT 2003


On Thu, 23 Oct 2003, Alexey Zelkin wrote:

> hi,
> 
> 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.

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().

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

-- 
Dan Eischen



More information about the freebsd-threads mailing list