Project

General

Profile

Backport #7999

bootstarap test hungs at threading tests

Added by ko1 (Koichi Sasada) over 6 years ago. Updated over 6 years ago.

Status:
Closed
Priority:
Normal
[ruby-core:53095]

Description

On [ruby-list:49232], Ootani-san reported that Ruby 2.0.0p0 hungs on bootstarap test hungs at threading tests.

assert_equal 'true', %{
t = Thread.new { loop {} }
begin
pid = fork {
exit t.status != "run"
}
Process.wait pid
$?.success?
rescue NotImplementedError
true
end
}

He rewrites to " t = Thread.new { loop {sleep 1} }" and it work successfully.
His environment is CentOS6.3 and VMware.
He doubts this issue caused only on single-core processor because there is no problem on multi-core VM setting.

I also observed same issue on VirtualBox with Ubuntu. I haven't check yet that it is only on single-core or not.

I want to clarify the reason of this issue.
Please give information about your environment if you have same issue.


Related issues

Related to Ruby master - Bug #6098: Re: GVL改善案ClosedActions

Associated revisions

Revision bcf12936
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39686 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 39686
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 39686
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 39686
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 39686
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 39686
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 39686
Added by kosaki (Motohiro KOSAKI) over 6 years ago

  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 6901ebcb
Added by nagachika (Tomoyuki Chikanaga) over 6 years ago

merge revision(s) 39679,39682,39683,39685,39686,39694: [Backport #7999]

    * thread_pthread.c (set_nonblock): new helper function for set
      O_NONBLOCK.

    * thread_pthread.c (rb_thread_create_timer_thread): set O_NONBLOCK
      to timer_thread_pipe[0] too.

    * thread_pthread.c (consume_communication_pipe): retry when
      read returned CCP_READ_BUFF_SIZE.

    * thread_pthread.c (rb_thread_create_timer_thread): factor out
      creating communication pipe logic into separate function.

    * thread_pthread.c (setup_communication_pipe): new helper function.

    * thread_pthread.c (set_nonblock): moves a definition before
      setup_communication_pipe.

    * thread_pthread.c (rb_thread_wakeup_timer_thread_fd): add fd
      argument and remove hardcoded dependency of timer_thread_pipe[1].

    * thread_pthread.c (consume_communication_pipe): add fd argument.

    * thread_pthread.c (close_communication_pipe): ditto.

    * thread_pthread.c (timer_thread_sleep): adjust the above changes.

    * thread_pthread.c (setup_communication_pipe_internal): factor
      out pipe initialize logic.

    * thread_pthread.c (ARRAY_SIZE): new.

    * thread_pthread.c (gvl_acquire_common): use low priority
      notification for avoiding timer thread interval confusion.
      If we use timer_thread_pipe[1], every gvl_yield() request
      one more gvl_yield(). It lead to thread starvation.
      [Bug #7999] [ruby-core:53095]

    * thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low
      to reserved fds.

    * process.c (setup_communication_pipe): remove unused function.
      it was unintentionally added r39683.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_0_0@39727 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 39727
Added by nagachika (Tomoyuki Chikanaga) over 6 years ago

merge revision(s) 39679,39682,39683,39685,39686,39694: [Backport #7999]

* thread_pthread.c (set_nonblock): new helper function for set
  O_NONBLOCK.

* thread_pthread.c (rb_thread_create_timer_thread): set O_NONBLOCK
  to timer_thread_pipe[0] too.

* thread_pthread.c (consume_communication_pipe): retry when
  read returned CCP_READ_BUFF_SIZE.

* thread_pthread.c (rb_thread_create_timer_thread): factor out
  creating communication pipe logic into separate function.

* thread_pthread.c (setup_communication_pipe): new helper function.

* thread_pthread.c (set_nonblock): moves a definition before
  setup_communication_pipe.

* thread_pthread.c (rb_thread_wakeup_timer_thread_fd): add fd
  argument and remove hardcoded dependency of timer_thread_pipe[1].

* thread_pthread.c (consume_communication_pipe): add fd argument.

* thread_pthread.c (close_communication_pipe): ditto.

* thread_pthread.c (timer_thread_sleep): adjust the above changes.

* thread_pthread.c (setup_communication_pipe_internal): factor
  out pipe initialize logic.

* thread_pthread.c (ARRAY_SIZE): new.

* thread_pthread.c (gvl_acquire_common): use low priority
  notification for avoiding timer thread interval confusion.
  If we use timer_thread_pipe[1], every gvl_yield() request
  one more gvl_yield(). It lead to thread starvation.
  [Bug #7999] [ruby-core:53095]

* thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low
  to reserved fds.

* process.c (setup_communication_pipe): remove unused function.
  it was unintentionally added r39683.

History

Updated by kosaki (Motohiro KOSAKI) over 6 years ago

I could reproduced. try taskset command.

e.g.
taskset -c 0 ./ruby test.rb

Updated by kosaki (Motohiro KOSAKI) over 6 years ago

  • Status changed from Open to Assigned
  • Assignee changed from ko1 (Koichi Sasada) to kosaki (Motohiro KOSAKI)

main thread never exit from rb_threadptr_execute_interrupts() because timer thread wake-up lead to increase t->running_time_us and exhaust thread time slice.

Updated by kosaki (Motohiro KOSAKI) over 6 years ago

This issue was introduced at r35163 (see [Bug#6098]).

#4

Updated by kosaki (Motohiro KOSAKI) over 6 years ago

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

This issue was solved with changeset r39686.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


  • thread_pthread.c (ARRAY_SIZE): new.
  • thread_pthread.c (gvl_acquire_common): use low priority notification for avoiding timer thread interval confusion. If we use timer_thread_pipe[1], every gvl_yield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999] [ruby-core:53095]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.
#5

Updated by kosaki (Motohiro KOSAKI) over 6 years ago

  • Tracker changed from Bug to Backport
  • Project changed from Ruby master to Backport200
  • Category deleted (core)
  • Status changed from Closed to Assigned
  • Assignee changed from kosaki (Motohiro KOSAKI) to nagachika (Tomoyuki Chikanaga)
  • Target version deleted (2.1.0)

Please backport following commits.

r39679 - set O_NONBLOCK to timer_thread_pipe[0] too.
r39682 - retry when read returned CCP_READ_BUFF_SIZE.
r39683 - setup_communication_pipe: new helper function.
r39685 - add fd argument and remove hardcoded dependency of timer_thread_pipe.
r39686 - use low priority notification for avoiding timer thread interval confusion.

Updated by kosaki (Motohiro KOSAKI) over 6 years ago

Oops, please backport r39694 too.

#7

Updated by nagachika (Tomoyuki Chikanaga) over 6 years ago

  • Status changed from Assigned to Closed

This issue was solved with changeset r39727.
Koichi, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.


merge revision(s) 39679,39682,39683,39685,39686,39694: [Backport #7999]

* thread_pthread.c (set_nonblock): new helper function for set
  O_NONBLOCK.

* thread_pthread.c (rb_thread_create_timer_thread): set O_NONBLOCK
  to timer_thread_pipe[0] too.

* thread_pthread.c (consume_communication_pipe): retry when
  read returned CCP_READ_BUFF_SIZE.

* thread_pthread.c (rb_thread_create_timer_thread): factor out
  creating communication pipe logic into separate function.

* thread_pthread.c (setup_communication_pipe): new helper function.

* thread_pthread.c (set_nonblock): moves a definition before
  setup_communication_pipe.

* thread_pthread.c (rb_thread_wakeup_timer_thread_fd): add fd
  argument and remove hardcoded dependency of timer_thread_pipe[1].

* thread_pthread.c (consume_communication_pipe): add fd argument.

* thread_pthread.c (close_communication_pipe): ditto.

* thread_pthread.c (timer_thread_sleep): adjust the above changes.

* thread_pthread.c (setup_communication_pipe_internal): factor
  out pipe initialize logic.

* thread_pthread.c (ARRAY_SIZE): new.

* thread_pthread.c (gvl_acquire_common): use low priority
  notification for avoiding timer thread interval confusion.
  If we use timer_thread_pipe[1], every gvl_yield() request
  one more gvl_yield(). It lead to thread starvation.
  [Bug #7999] [ruby-core:53095]

* thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low
  to reserved fds.

* process.c (setup_communication_pipe): remove unused function.
  it was unintentionally added r39683.

Also available in: Atom PDF