I am working under Linux, using Perl 5.8.0, and I have a shared object that takes a callback, starts a pthread and when the thread finishes, calls the callback. This works fine if done in C.
However, I need to write a Perl extension (using XS and following mainly Strategies for storing callback) around this shared object, and I cannot get it to work properly.
I can register a callback to a Perl sub. I can call this sub all right as long as I'm in the main thread. However, if the thread calls the callback the whole thing crashes (segmentation fault), before it even enters the XS function that perpares and calls the Perl sub.
Here's some code that doesn't work (my excuses if it's too much code, I tried to keep it to a bare minumum):

My shared object mylib.c:
//gcc -o libmylib.so -shared -fpic mylib.c -lpthread #include "mylib.h" #include <pthread.h> static lib_work_done_callback_t GCB; static void *GData; static void *run( void *Arg ) { sleep( 3 ); printf( "Calling callback() from thread.\n" ); GCB( GData ); /* crashes here */ printf( "Calling callback() from thread done.\n" ); return( NULL ); } int lib_RegisterWorkDoneCallback( void *a, lib_work_done_callback_t CB, void *Data ) { pthread_t thread; pthread_attr_t attr; int res = 0; GCB = CB; GData = Data; pthread_attr_init( &attr ); pthread_attr_setdetachstate( &attr, PTHREAD_CREATE_DETACHED ); if( pthread_create( &thread, &attr, run, NULL ) ) { printf( "Error: Could not create thread.\n" ); res = 1; } pthread_attr_destroy( &attr ); return( res ); }
The header for the library mylib.h:
#ifndef mylib_h #define mylib_h typedef void (*lib_work_done_callback_t)( void * ); int lib_RegisterWorkDoneCallback( void *a, lib_work_done_callback_t CB, void *Data ); #endif
My XS MyLib.xs:
#include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "ppport.h" #include "../mylib.h" #define MY_CXT_KEY "MyLib::_guts" XS_VERSION typedef struct { HV * Mapping; } my_cxt_t; START_MY_CXT static void lib_RegisterWorkDoneCallback_if( void *Data ) { dSP; dMY_CXT; printf( "Performing perl callback.\n" ); fflush( stdout ); ENTER; SAVETMPS; SV ** sv; sv = hv_fetch( MY_CXT.Mapping, (void*)&Data, sizeof(Data), FALSE ); if( sv == (SV**)NULL) croak("Internal error. No callback registered.\n"); PUSHMARK( sp ); XPUSHs( sv_2mortal( newSViv( (int) Data ) ) ); PUTBACK; perl_call_sv( *sv, G_DISCARD ); FREETMPS; LEAVE; } #include "const-c.inc" MODULE = MyLib PACKAGE = MyLib PREFIX = lib_ INCLUDE: const-xs.inc BOOT: { MY_CXT_INIT; MY_CXT.Mapping = (HV*)NULL; } int lib_RegisterWorkDoneCallback(A, Callback, Data) void *A SV *Callback void *Data CODE: { dMY_CXT; printf( "Registering Perl callback.\n" ); fflush( stdout ); if( MY_CXT.Mapping == (HV*)NULL ) MY_CXT.Mapping = newHV(); hv_store( MY_CXT.Mapping, (void*)&Data, sizeof( Data ), newSVsv( Callback ), 0 ); RETVAL = lib_RegisterWorkDoneCallback( A, &lib_RegisterWorkDoneCallback_if, Data ); } OUTPUT: RETVAL
My PM MyLib.pm:
package MyLib; use 5.008; use strict; use warnings; use Carp; require Exporter; use AutoLoader; our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); our @EXPORT = qw( ); our $VERSION = '0.01'; sub AUTOLOAD { my $constname; our $AUTOLOAD; ($constname = $AUTOLOAD) =~ s/.*:://; croak "&MyLib::constant not defined" if $constname eq 'constant'; my ($error, $val) = constant($constname); if ($error) { croak $error; } { no strict 'refs'; *$AUTOLOAD = sub { $val }; } goto &$AUTOLOAD; } require XSLoader; XSLoader::load('MyLib', $VERSION); 1; __END__
Any tips or hints about what to do ? I saw a post (from 1999!) on google groups from Jan Dubois (Google groups) about something like this, but I have no idea how to wait for Perl's main thread, how to synchronise the two threads, if it at all is relevant today.
I've been hitting my head bloody over this; I hope someone can help.
Thanks!

In reply to Callback from threaded shared library by Anonymous Monk

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.