Background threads and Process.daemon

Hello all,

I'm seeing some unexpected behavior with background threads and
Process.daemon, and wondering whether I'm just doing something
wrong/unsupported, or if I've hit upon a Ruby bug.

Here's a test case that exposes the oddness I'm seeing:

This code spawns a background thread that loops calling sleep(1)
repeatedly, then calls Process.daemon, and finally puts the main thread
into a sleep loop.

To reproduce the strangeness, run it, find the PID of the daemonized
process, and send it SIGQUIT. Instead of exiting, the process gets stuck in
a loop in rb_thread_terminate_all that looks like this:

In addition, after daemonization, attaching to the process with gdb shows
only 2 native threads. Prior to daemonization, three native threads are
visible from gdb.

Is this (creating a background thread and then daemonizing) expected to
work? Am I doing something else wrong here? I'm using ruby 1.9.3p327 on
Mac OS X 10.8.2.

Thanks!
Ben

Ah, I believe I've found the issue. Process.daemon calls daemon(3), which
calls fork(). The POSIX documentation for fork says:

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.

So this seems a misunderstanding of daemon() semantics on my part rather
than a bug.

Sorry for the noise!
Ben

···

From: fork

On Thursday, January 17, 2013, Ben Weintraub wrote:

Hello all,

I'm seeing some unexpected behavior with background threads and
Process.daemon, and wondering whether I'm just doing something
wrong/unsupported, or if I've hit upon a Ruby bug.

Here's a test case that exposes the oddness I'm seeing:
bgtest.rb · GitHub

This code spawns a background thread that loops calling sleep(1)
repeatedly, then calls Process.daemon, and finally puts the main thread
into a sleep loop.

To reproduce the strangeness, run it, find the PID of the daemonized
process, and send it SIGQUIT. Instead of exiting, the process gets stuck in
a loop in rb_thread_terminate_all that looks like this:
gist:4561403 · GitHub

In addition, after daemonization, attaching to the process with gdb shows
only 2 native threads. Prior to daemonization, three native threads are
visible from gdb.

Is this (creating a background thread and then daemonizing) expected to
work? Am I doing something else wrong here? I'm using ruby 1.9.3p327 on
Mac OS X 10.8.2.

Thanks!
Ben