diff options
author | Tony Cook <tony@develop-help.com> | 2019-02-27 12:01:40 +1100 |
---|---|---|
committer | Tony Cook <tony@develop-help.com> | 2019-03-08 10:36:13 +1100 |
commit | 609761014c471773184e867d1587daac35036aef (patch) | |
tree | cae1ae2dbb72c2f906da906dbed4c5bb9661d439 /lib/perl5db | |
parent | d22170b0f355b196776681a081a50e5d7a7520cf (diff) | |
download | perl-609761014c471773184e867d1587daac35036aef.tar.gz |
(perl #124203) avoid a deadlock in DB::sub
I don't know how this ever worked.
Previously, DB::sub() would hold a lock on $DB::DBGR for it's entire
body, including the call to the subroutine being called.
This could cause problems in two cases:
a) on creation of a new thread, CLONE() is called in the context of
the new interpreter before the new thread is created. So you'd have a
sequence like:
threads->new
DB::sub for threads::new (lock $DBGR)
call into threads::new which creates a new interpreter
Cwd::CLONE() (in the new interpreter)
DB::sub for Cwd::CLONE (in the new interpreter) (deadlock trying to lock $DBGR)
One workaround I tried for this was to prevent pp_entersub calling
DB::sub if we were cloning (by checking PL_ptr_table). This did
improve matters, but wasn't needed in the final patch.
Note that the recursive lock on $DBGR would have been fine if the new
code was executing in the same interpreter, since the locking code
simply bumps a reference count if the current interpreter already
holds the lock.
b) when the called subroutine blocks. For the test case this could
happen with the call to $thr->join. There would be a sequence like:
(parent) $thr->join
(parent) DB::sub for threads::join (lock $DBGR)
(parent) call threads::join and block
(child) try to call main::sub1
(child) DB::sub for main::sub1 (deadlock trying to lock $DBGR)
This isn't limited to threads::join obviously, one thread could be
waiting for input, sleeping, or performing a complex calculation.
The solution I chose here was the obvious one - don't hold the lock
for the actual call.
This required some rearrangement of the code and removed some
duplication too.
Diffstat (limited to 'lib/perl5db')
-rw-r--r-- | lib/perl5db/t/rt-124203 | 7 |
1 files changed, 7 insertions, 0 deletions
diff --git a/lib/perl5db/t/rt-124203 b/lib/perl5db/t/rt-124203 new file mode 100644 index 0000000000..85ab7b0b27 --- /dev/null +++ b/lib/perl5db/t/rt-124203 @@ -0,0 +1,7 @@ +use threads; +my $thr = threads->create(\&sub1); +sub sub1 { + print("In the thread\n"); +} +$thr->join; +print "Finished\n";
\ No newline at end of file |