Bug #9751

Process.wait does not work correctly in a thread

Added by Sam Saffron about 1 year ago. Updated about 1 year ago.

[ruby-core:62070]
Status:Closed
Priority:Normal
Assignee:-
ruby -v:1.9, 2.0, 2.1, 2.2 Backport:2.0.0: DONE, 2.1: DONE

Description

The following code fails under Ruby 1.9+, used to work on 1.8 with green threads

def test
  if pid = fork
    puts "child pid is #{pid} waiting ..."
    begin
      Process.wait(pid)
      puts "child exited"
    rescue => e
      p e
    end
  else
    sleep 3
    puts "exiting child"
    exit 0
  end
end

# this works as expected
test

puts "testing in thread"

# this will hang
Thread.new do
  test
end.join

Additionally on SIGINT I am seeing a zombie + [BUG] pthread_mutex_lock: Invalid argument (EINVAL)

Associated revisions

Revision 45899
Added by Nobuyoshi Nakada about 1 year ago

thread.c: stop if forked in a sub-thread

  • thread.c (thread_start_func_2): stop if forked in a sub-thread, the thread has become the main thread. [Bug #9751]

Revision 45899
Added by Nobuyoshi Nakada about 1 year ago

thread.c: stop if forked in a sub-thread

  • thread.c (thread_start_func_2): stop if forked in a sub-thread, the thread has become the main thread. [Bug #9751]

Revision 46497
Added by Tomoyuki Chikanaga about 1 year ago

merge revision(s) r45899: [Backport #9751]

* thread.c (thread_start_func_2): stop if forked in a sub-thread,
  the thread has become the main thread.
   [Bug #9751]

Revision 46518
Added by Usaku NAKAMURA about 1 year ago

merge revision(s) 45899: [Backport #9751]

* thread.c (thread_start_func_2): stop if forked in a sub-thread,
  the thread has become the main thread.
   [Bug #9751]

History

#1 Updated by Eric Wong about 1 year ago

sam.saffron@gmail.com wrote:

def test
  if pid = fork

<snip>

  else
    sleep 3
    puts "exiting child"
    exit 0

A workaround is to use exit!(0) in the child.
Normal "exit" may be buggy, looking into it.

  end
end

#2 Updated by Eric Wong about 1 year ago

The following one-liner fixes the case where "exit" is called.
However, when "exit"/"exit!" is omitted entirely, it still hangs.
I am out of time for today...

--- a/thread.c
+++ b/thread.c
@@ -3799,6 +3799,7 @@ rb_thread_atfork(void)
 {
     rb_thread_atfork_internal(terminate_atfork_i);
     GET_THREAD()->join_list = NULL;
+    GET_THREAD()->tag = NULL;

     /* We don't want reproduce CVE-2003-0900. */
     rb_reset_random_seed();

(indented so I hope it looks OK in redmine)

#3 Updated by Nobuyoshi Nakada about 1 year ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

Applied in changeset r45899.


thread.c: stop if forked in a sub-thread

  • thread.c (thread_start_func_2): stop if forked in a sub-thread, the thread has become the main thread. [Bug #9751]

#4 Updated by Tomoyuki Chikanaga about 1 year ago

  • Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN to 2.0.0: REQUIRED, 2.1: REQUIRED

#5 Updated by Tomoyuki Chikanaga about 1 year ago

  • Backport changed from 2.0.0: REQUIRED, 2.1: REQUIRED to 2.0.0: REQUIRED, 2.1: DONE

Backported into ruby_2_1 branch at r46497.

#6 Updated by Usaku NAKAMURA about 1 year ago

backported into ruby_2_0_0 at r46518.

#7 Updated by Usaku NAKAMURA about 1 year ago

  • Backport changed from 2.0.0: REQUIRED, 2.1: DONE to 2.0.0: DONE, 2.1: DONE

Also available in: Atom PDF