Backport #7999

bootstarap test hungs at threading tests

Added by Koichi Sasada about 1 year ago. Updated about 1 year 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 39727
Added by Tomoyuki Chikanaga about 1 year 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 1 year ago

I could reproduced. try taskset command.

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

#2 Updated by Motohiro KOSAKI about 1 year ago

  • Status changed from Open to Assigned
  • Assignee changed from Koichi Sasada to Motohiro KOSAKI

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

#3 Updated by Motohiro KOSAKI about 1 year ago

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

#4 Updated by Motohiro KOSAKI about 1 year 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.


  • threadpthread.c (ARRAYSIZE): new.
  • threadpthread.c (gvlacquirecommon): use low priority notification for avoiding timer thread interval confusion. If we use timerthreadpipe[1], every gvlyield() request one more gvl_yield(). It lead to thread starvation. [Bug #7999]
  • threadpthread.c (rbreservedfdp): adds timerthreadpipe_low to reserved fds.

#5 Updated by Motohiro KOSAKI about 1 year ago

  • Tracker changed from Bug to Backport
  • Project changed from ruby-trunk to Backport200
  • Category deleted (core)
  • Status changed from Closed to Assigned
  • Assignee changed from Motohiro KOSAKI to Tomoyuki Chikanaga
  • Target version deleted (2.1.0)

Please backport following commits.

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

#6 Updated by Motohiro KOSAKI about 1 year ago

Oops, please backport r39694 too.

#7 Updated by Tomoyuki Chikanaga about 1 year 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