Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Perl: porters

[perl #114378] cond_signal does not wake up a thread

 

 

Perl porters RSS feed   Index | Next | Previous | View Threaded


perlbug-followup at perl

Aug 2, 2012, 2:36 AM

Post #1 of 6 (244 views)
Permalink
[perl #114378] cond_signal does not wake up a thread

# New Ticket Created by Matti Linnanvuori
# Please include the string: [perl #114378]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=114378 >


This is a bug report for perl from matti [at] portalify,
generated with the help of perlbug 1.39 running under perl 5.12.3.


-----------------------------------------------------------------
[Please describe your issue here]

cond_signal does not wake another thread up even though I think it should.
The same problem appears in perl 5.10.0 in SLES 11 SP1.
The main thread joins the other thread forever:

8/2/12 12:19:01.930 PM aplicom: Failed to receive data from the socket: Interrupted system call
8/2/12 12:19:01.930 PM aplicom: Closing the socket
8/2/12 12:19:01.930 PM aplicom: Killing the post thread
8/2/12 12:19:01.931 PM aplicom: Locking to signal termination
8/2/12 12:19:01.931 PM aplicom: Signaling the post thread to terminate
8/2/12 12:19:01.931 PM aplicom: Joining the post thread

sub post {
$SIG{'TERM'} = \&termination_flag;

my $ua = LWP::UserAgent->new;
$ua->timeout( $configuration->{'timeout'} );

while ($run) {
my %post;
{
syslog LOG_DEBUG, "Locking to check for new location GeoJSON data";
lock %location;
until ( %location or not $run ) {
syslog LOG_DEBUG, "Waiting for location GeoJSON data";
cond_wait %location;
}
%post = %location;
}
if (%post) {
my %feature;
while ( my ( $id, $feature ) = each %post ) {
$feature{$id} = encode_json $feature;
}
my $content = '{"type":"FeatureCollection","features":['
. join( ',', values %feature ) . ']}';
syslog LOG_INFO, "Posting location data $content";
my $response = $ua->post(
$configuration->{'url'},
'Content-Type' => 'application/json',
'Content' => $content
);

if ( $response->is_success ) {
syslog LOG_INFO, $response->as_string;
syslog LOG_DEBUG, "Locking to delete the posted location data";
lock %location;
while ( my ( $id, $feature ) = each %location ) {
if ( $feature{$id} eq encode_json $feature ) {
delete $location{$id};
}
}
}
else {
syslog LOG_WARNING, $response->as_string;
sleep $run * $configuration->{'retry'};
}
}
}
syslog LOG_NOTICE, "The post subroutine terminating";
}

until ( $thread = threads->create('post') or not $run ) {
syslog LOG_ERR, "Failed to create the post thread: $!. Retrying";
sleep $run * $configuration->{'retry'};
}

if ( defined $thread ) {
syslog LOG_NOTICE, "Killing the post thread";
$thread->kill('SIGTERM');
}

syslog LOG_NOTICE, "Locking to signal termination";
lock %location;
syslog LOG_NOTICE, "Signaling the post thread to terminate";
cond_signal %location;

if ( defined $thread ) {
syslog LOG_NOTICE, "Joining the post thread";
$thread->join();
}


GNU gdb 6.3.50-20050815 (Apple version gdb-1752) (Sat Jan 28 03:02:46 UTC 2012)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "x86_64-apple-darwin".
(gdb) attach 363
NRkm.!28DQ
Attaching to process 363.
Reading symbols for shared libraries . done
Reading symbols for shared libraries ......................................... done
Reading symbols for shared libraries + done
0x00007fff960ffe42 in __semwait_signal ()
(gdb) NRkm.!28DQ
Undefined command: "NRkm". Try "help".
(gdb) bt
#0 0x00007fff960ffe42 in __semwait_signal ()
#1 0x00007fff93bec97e in pthread_join ()
#2 0x000000010d0f2def in XS_threads_join ()
#3 0x000000010cfe7a9c in Perl_pp_entersub ()
#4 0x000000010cfe5ec8 in Perl_runops_standard ()
#5 0x000000010cf8ce51 in perl_run ()
#6 0x000000010cf74d32 in main ()
(gdb) thread 1
[Switching to thread 1 (process 363), "com.apple.main-thread"]
0x00007fff960ffe42 in __semwait_signal ()
(gdb) bt
#0 0x00007fff960ffe42 in __semwait_signal ()
#1 0x00007fff93bec97e in pthread_join ()
#2 0x000000010d0f2def in XS_threads_join ()
#3 0x000000010cfe7a9c in Perl_pp_entersub ()
#4 0x000000010cfe5ec8 in Perl_runops_standard ()
#5 0x000000010cf8ce51 in perl_run ()
#6 0x000000010cf74d32 in main ()
(gdb) thread 2
[Switching to thread 2 (process 363)]
0x00007fff960ffbca in __psynch_cvwait ()
(gdb) bt
#0 0x00007fff960ffbca in __psynch_cvwait ()
#1 0x00007fff93c3a274 in _pthread_cond_wait ()
#2 0x000000010d23de78 in XS_threads__shared_cond_wait ()
#3 0x000000010cfe7a9c in Perl_pp_entersub ()
#4 0x000000010cfe5ec8 in Perl_runops_standard ()
#5 0x000000010cf8c6af in Perl_call_sv ()
#6 0x000000010d0f512b in ithread_mg_free ()
#7 0x00007fff93c368bf in _pthread_start ()
#8 0x00007fff93c39b75 in thread_start ()
(gdb)


[Please do not change anything below this line]
-----------------------------------------------------------------
---
Flags:
category=library
severity=medium
module=threads::shared
---
Site configuration information for perl 5.12.3:

Configured by _mdnsresponder at Wed May 25 17:39:19 PDT 2011.

Summary of my perl5 (revision 5 version 12 subversion 3) configuration:

Platform:
osname=darwin, osvers=11.0, archname=darwin-thread-multi-2level
uname='darwin doublemagnum.apple.com 11.0 darwin kernel version 11.0.0: wed dec 22 11:00:23 pst 2010; root:xnu-1699.18.1~1release_x86_64 x86_64 '
config_args='-ds -e -Dprefix=/usr -Dccflags=-g -pipe -Dldflags= -Dman3ext=3pm -Duseithreads -Duseshrplib -Dinc_version_list=none -Dcc=llvm-gcc-4.2'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=define, use64bitall=define, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='llvm-gcc-4.2', ccflags ='-arch x86_64 -arch i386 -g -pipe -fno-common -DPERL_DARWIN -fno-strict-aliasing -fstack-protector -I/usr/local/include',
optimize='-Os',
cppflags='-g -pipe -fno-common -DPERL_DARWIN -fno-strict-aliasing -fstack-protector -I/usr/local/include'
ccversion='', gccversion='4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)', gccosandvers=''
intsize=4, longsize=8, ptrsize=8, doublesize=8, byteorder=12345678
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=16
ivtype='long', ivsize=8, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=8, prototype=define
Linker and Libraries:
ld='llvm-gcc-4.2 -mmacosx-version-min=10.7', ldflags ='-arch x86_64 -arch i386 -fstack-protector -L/usr/local/lib'
libpth=/usr/local/lib /usr/lib
libs=-ldbm -ldl -lm -lutil -lc
perllibs=-ldl -lm -lutil -lc
libc=, so=dylib, useshrplib=true, libperl=libperl.dylib
gnulibc_version=''
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=bundle, d_dlsymun=undef, ccdlflags=' '
cccdlflags=' ', lddlflags='-arch x86_64 -arch i386 -bundle -undefined dynamic_lookup -L/usr/local/lib -fstack-protector'

Locally applied patches:
/Library/Perl/Updates/<version> comes before system perl directories
installprivlib and installarchlib points to the Updates directory

---
@INC for perl 5.12.3:
/Library/Perl/5.12/darwin-thread-multi-2level
/Library/Perl/5.12
/Network/Library/Perl/5.12/darwin-thread-multi-2level
/Network/Library/Perl/5.12
/Library/Perl/Updates/5.12.3/darwin-thread-multi-2level
/Library/Perl/Updates/5.12.3
/System/Library/Perl/5.12/darwin-thread-multi-2level
/System/Library/Perl/5.12
/System/Library/Perl/Extras/5.12/darwin-thread-multi-2level
/System/Library/Perl/Extras/5.12
.

---
Environment for perl 5.12.3:
DYLD_LIBRARY_PATH (unset)
HOME=/Users/matti
LANG (unset)
LANGUAGE (unset)
LC_CTYPE=UTF-8
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/usr/local/git/bin
PERL_BADLANG (unset)
SHELL=/bin/bash


perlbug-comment at perl

Aug 2, 2012, 6:00 AM

Post #2 of 6 (226 views)
Permalink
[perl #114378] cond_signal does not wake up a thread [In reply to]

This a deadlock because the killing thread holds a lock while joining.


davem at iabyn

Aug 2, 2012, 8:16 AM

Post #3 of 6 (222 views)
Permalink
Re: [perl #114378] cond_signal does not wake up a thread [In reply to]

On Thu, Aug 02, 2012 at 02:36:34AM -0700, Matti Linnanvuori wrote:
> cond_signal does not wake another thread up even though I think it should.
> The same problem appears in perl 5.10.0 in SLES 11 SP1.
> The main thread joins the other thread forever:

Its difficult to say for certain, since you don't provide complete code,
but it looks like the fault is here:

> lock %location;
> syslog LOG_NOTICE, "Signaling the post thread to terminate";
> cond_signal %location;
>
> if ( defined $thread ) {
> syslog LOG_NOTICE, "Joining the post thread";
> $thread->join();
> }

You don't unlock %location before trying to join the thread. Note that
cond_signal() itself does not unlock the variable (and so cond_wait()
hangs trying to relock the var).

So you probably need to wrap the lock and cond_signal lines above in a
{... } block, so that the lock is released before attempting to join

As a more general comment, I'd recommend try to avoid using cond_wait and
cond_signal wherever possible. They are a very low-level interface, and
are notoriously hard to get right. Use something higher level: often
a simple perl-level lock is sufficient (it uses condition variables under
the hood to ensure that a process waiting on a lock gets woken up),
or possibly something like Thread::Queue.

--
This is a great day for France!
-- Nixon at Charles De Gaulle's funeral


perlbug-comment at perl

Aug 2, 2012, 10:17 PM

Post #4 of 6 (222 views)
Permalink
[perl #114378] cond_signal does not wake up a thread [In reply to]

The bug was indeed in that the joining thread held the lock while the thread being joined waited
for the same lock in cond_wait. So this is not such a Perl bug, even though the warning that
cond_wait emits when used on an unlocked variable contributed to the bug, so the Perl
specification is partly to blame.


perlbug-comment at perl

Aug 2, 2012, 10:21 PM

Post #5 of 6 (227 views)
Permalink
[perl #114378] cond_signal does not wake up a thread [In reply to]

What I meant that if Perl did not emit a warning when calling cond_signal on an unlocked
variable, I would not have locked the variable and so the bug would not have been written. The
no warnings 'threads' to avoid the warning seems such an unclean hack.


davem at iabyn

Aug 3, 2012, 3:08 AM

Post #6 of 6 (223 views)
Permalink
Re: [perl #114378] cond_signal does not wake up a thread [In reply to]

On Thu, Aug 02, 2012 at 10:21:24PM -0700, Matti Linnanvuori via RT wrote:
> What I meant that if Perl did not emit a warning when calling cond_signal on an unlocked
> variable, I would not have locked the variable and so the bug would not have been written. The
> no warnings 'threads' to avoid the warning seems such an unclean hack.

I think you misunderstand. For correct use of cond_signal, you *must* hold
the lock first(*), so perl's warning is correct. Your mistake was in not
subsequently unlocking the var.

* because otherwise you can't be sure that the other thread has yet
reached cond_wait(), so the signal could get lost and deadlock ensue.
Which is another reason why you should avoid cond_wait/signal for most
code. It's too hard to get right.

--
"There's something wrong with our bloody ships today, Chatfield."
-- Admiral Beatty at the Battle of Jutland, 31st May 1916.

Perl porters RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.