Backport #7999

bootstarap test hungs at threading tests

Added by Koichi Sasada about 2 years ago. Updated about 2 years ago.

[ruby-core:53095]
Status:Closed
Priority:Normal
Assignee:Tomoyuki Chikanaga

Description

On , 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 trunk - Bug #6098: Re: GVL改善案 Closed

Associated revisions

Revision 39686
Added by Motohiro KOSAKI about 2 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]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

Revision 39727
Added by Tomoyuki Chikanaga about 2 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] 

* 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

#1 Updated by Motohiro KOSAKI about 2 years ago

I could reproduced. try taskset command.

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

#2 Updated by Motohiro KOSAKI about 2 years ago

  • Status changed from Open to Assigned
  • Assignee changed from Koichi Sasada to 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.

#3 Updated by Motohiro KOSAKI about 2 years ago

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

#4 Updated by Motohiro KOSAKI about 2 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]
  • thread_pthread.c (rb_reserved_fd_p): adds timer_thread_pipe_low to reserved fds.

#5 Updated by Motohiro KOSAKI about 2 years ago

  • Status changed from Closed to Assigned
  • Tracker changed from Bug to Backport
  • Project changed from Ruby trunk to Backport200
  • Category deleted (core)
  • Assignee changed from Motohiro KOSAKI to 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.

#6 Updated by Motohiro KOSAKI about 2 years ago

Oops, please backport r39694 too.

#7 Updated by Tomoyuki Chikanaga about 2 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] 

* 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