in reply to Re^15: Perl crash during perl_clone
in thread Perl crash during perl_clone
As best I can tell, this does everything your samples do. I've discarded everything that doesn't seem to be needed.
This sets up 4 different callbacks, from a different package than where the callbacks are set up. They are called back randomly.
Each CCB passes through a value from C->perl. Each PCB accepts and displays that value; and modifies a closed over variable.
This runs perfectly, flat out using all four of my cores for as long as I choose to leave it.
The errors during global destruction--when the perl thread ends--are simply because the C-threads are still running and continue trying to call back to perl as it is throwing everything away.
If I try to pass the callback addresses by code-reference instead of name, I too get traps. I don't know why, so don't do that.
I don't think there is much more I can do for you. If the below (suitably adapted to your platform), doesn't work for you, then it will require more expertise than I have in one more of: XS, *nix, perlguts.
Update: Had to put back the ENTER/SAVETMPS/FRETMPS/LEAVE brackets otherwise it leaked memory.
#! perl -slw use strict; use Inline C => Config => BUILD_NOISY => 1; use Inline C => <<'END_C', NAME => '_867652', CLEAN_AFTER_BUILD => 0; PerlInterpreter *saved; SV *callbacks[ 4 ]; VOID CALLBACK cbProc( int cbn, DWORD time ) { printf( "CCB[%d]: %u\n", cbn, time ); PERL_SET_CONTEXT( saved ); { dSP; ENTER; SAVETMPS; PUSHMARK( SP ); XPUSHs( sv_2mortal( newSVuv( (UV)time ) ) ); PUTBACK; call_sv( callbacks[ cbn ], G_DISCARD ); FREETMPS; LEAVE; } return; } void __cdecl thread( VOID *arg ) { while( Sleep( 1 ), 1 ) { // This is Win32 Sleep The argument is in + milliseconds! cbProc( rand() & 3, GetTickCount() ); } } void setCallback( SV *cb1, SV* cb2, SV *cb3, SV *cb4 ) { saved = Perl_get_context(); callbacks[0] = cb1; callbacks[1] = cb2; callbacks[2] = cb3; callbacks[3] = cb4; _beginthread( &thread, 0, NULL ); return; } END_C $|++; { package fred; my @c = (0) x 4; sub callback1 { ++$c[0]; print "PCB1: $_[0] ($c[0])"; return; } sub callback2 { ++$c[1]; print "PCB2: $_[0] ($c[1])"; return; } sub callback3 { ++$c[2]; print "PCB3: $_[0] ($c[2])"; return; } sub callback4 { ++$c[3]; print "PCB4: $_[0] ($c[3])"; return; } } setCallback( 'fred::callback1', 'fred::callback2', 'fred::callback3', +'fred::callback4' ); sleep 10; __END__ C:\test>867652 CCB[1]: 828337244 PCB2: 828337244 (1) CCB[3]: 828337244 PCB4: 828337244 (1) CCB[2]: 828337244 PCB3: 828337244 (1) CCB[0]: 828337260 PCB1: 828337260 (1) CCB[1]: 828337260 PCB2: 828337260 (2) CCB[0]: 828337260 PCB1: 828337260 (2) CCB[2]: 828337275 PCB3: 828337275 (2) CCB[2]: 828337275 PCB3: 828337275 (3) CCB[2]: 828337291 PCB3: 828337291 (4) CCB[0]: 828337291 PCB1: 828337291 (3) CCB[1]: 828337291 PCB2: 828337291 (3) ... PCB4: 828283221 (2033) CCB[0]: 828283221 PCB1: 828283221 (2039) CCB[3]: 828283221 Use of uninitialized value in null operation during global destruction +. Use of inherited AUTOLOAD for non-method main::() is deprecated during + global destruction. Use of uninitialized value $pkg in substitution (s///) at C:/Perl64/li +b/AutoLoader.pm line 73 during global destruction. Use of uninitialized value $pkg in substitution (s///) at C:/Perl64/li +b/AutoLoader.pm line 7m line 74 during global destruction. Use of uninitialized value $pkg in concatenation (.) or string at C:/P +erl64/lib/AutoLoader.pm line 74 during global destruction.
|
|---|