in reply to ActivePerl Gtk2::Helper Hangs
Running your first script, the perl process hung/blocked on a syncronous read to the NPFS Win32 Named Pipe that is the cmd.exe process std handles.
Here is some untested code for calling PeekNamedPipe
In Perl, the hang happened atntdll.dll!_KiFastSystemCallRet@0() ntdll.dll!_NtReadFile@36() + 0xc kernel32.dll!_ReadFile@20() + 0x67 > msvcr71.dll!_read_lk(int fh=0x00000005, void * buf=0x01ab870c, un +signed int cnt=0x00000001) Line 154 + 0x15 C msvcr71.dll!_read(int fh=0x00000005, void * buf=0x01ab870c, unsig +ned int cnt=0x00000001) Line 75 + 0xc C perl512.dll!win32_read(int fd=0x00000005, void * buf=0x01ab870c, +unsigned int cnt=0x00000001) Line 3746 + 0x12 C perl512.dll!PerlLIORead(IPerlLIO * piPerl=0x00285774, int handle= +0x00000005, void * buffer=0x01ab870c, unsigned int count=0x00000001) + Line 1049 + 0x11 C++ perl512.dll!Perl_pp_sysread(interpreter * my_perl=0x00393f04) Li +ne 1711 + 0x34 C perl512.dll!Perl_runops_debug(interpreter * my_perl=0x00393f04) +Line 2049 + 0xd C perl512.dll!Perl_call_sv(interpreter * my_perl=0x00393f04, sv * s +v=0x00829f74, volatile long flags=0x0000000a) Line 2605 + 0x36 C Glib.dll!gperl_closure_marshal(_GClosure * closure=0x00e025d0, _G +Value * return_value=0x0006f888, unsigned int n_param_values=0x000000 +02, const _GValue * param_values=0x0006f8a8, void * invocation_hint=0 +x00000000, void * marshal_data=0x00393f04) Line 105 + 0x96 C libgobject-2.0-0.dll!g_closure_invoke(_GClosure * closure=0x00e02 +5d0, _GValue * return_value=0x0006f888, unsigned int n_param_values=0 +x00000002, const _GValue * param_values=0x0006f8a8, void * invocation +_hint=0x00000000) Line 771 + 0x1b libgobject-2.0-0.dll!io_watch_closure_callback(_GIOChannel * chan +nel=0x00dcecf0, GIOCondition condition=G_IO_IN, void * data=0x00e025d +0) Line 94 + 0x15 libglib-2.0-0.dll!g_io_win32_dispatch(_GSource * source=0x00e0258 +0, int (void *)* callback=0x00b3c1c0, void * user_data=0x00e025d0) L +ine 979 + 0x1f libglib-2.0-0.dll!g_main_dispatch(_GMainContext * context=0x00dc9 +698) Line 2442 + 0xf libglib-2.0-0.dll!g_main_context_dispatch(_GMainContext * context +=0x00dc9698) Line 3013 + 0x9 libglib-2.0-0.dll!g_main_context_iterate(_GMainContext * context= +0x00dc9698, int block=0x00000001, int dispatch=0x00000001, _GThread * + self=0x00dc2ad8) Line 3091 + 0x9 libglib-2.0-0.dll!g_main_loop_run(_GMainLoop * loop=0x00e3c2c8) +Line 3299 + 0x13 libgtk-win32-2.0-0.dll!gtk_main() Line 1244 + 0x9 Gtk2.dll!XS_Gtk2_main(interpreter * my_perl=0x00393f04, cv * cv=0 +x0098af94) Line 523 C perl512.dll!Perl_pp_entersub(interpreter * my_perl=0x00393f04) L +ine 2882 + 0x10 C perl512.dll!Perl_runops_debug(interpreter * my_perl=0x00393f04) +Line 2049 + 0xd C perl512.dll!S_run_body(interpreter * my_perl=0x00393f04, long old +scope=0x00000001) Line 2308 + 0xd C perl512.dll!perl_run(interpreter * my_perl=0x00393f04) Line 2233 + + 0xd C perl512.dll!RunPerl(int argc=0x00000002, char * * argv=0x00283e08 +, char * * env=0x00284ed8) Line 270 + 0x9 C++ perl.exe!main(int argc=0x00000002, char * * argv=0x00283e08, char + * * env=0x00282c88) Line 23 + 0x12 C perl.exe!mainCRTStartup() Line 398 + 0xe C kernel32.dll!_BaseProcessStart@4() + 0x23
Long story short, select() on Win32, in C and in Perl, only works on sockets. Most POSIXy code assumes all FDs/handles are the same "type", so the authors never try to get Win32 async I/O models into their non-blocking POSIX code. You need to call PeekNamedPipe from kernel32 before doing a sysread() or read() from Perl. If the buffer has zero bytes, your read() will hang until some bytes are written to the pipe, or the other end of the pipe is closed.sub preview_call { my $buffer; my $rl = sysread($rfh,$buffer,1);<<<<<<<<<<<<<<<<<<<<<<<<<< if(defined($rl)){ print "$rl + $buffer\n"; while (Gtk2->events_pending()) {Gtk2->main_iteration();} return 1; }else{ print "undefined\n"; return 0; } }
Here is some untested code for calling PeekNamedPipe
Code is recycled from https://rt.perl.org/Ticket/Display.html?id=120330.use Win32API::File; use Win32; use Win32::API; { my $api; die "PeekNamedPipe" if ! ($api= Win32::API::More->Import("kernel32", " BOOL PeekNamedPipe( HANDLE hNamedPipe, LPVOID lpBuffer, DWORD nBufferSize, LPDWORD lpBytesRead, LPDWORD lpTotalBytesAvail, LPDWORD lpBytesLeftThisMessage );")); } ########################## my ($TotalBytesAvail, $ret) = (0); my $hnd = Win32API::File::FdGetOsFHandle($rfh->fileno()); #get Win32 k +ernel handle from Perl land if($hnd == Win32API::File::INVALID_HANDLE_VALUE()) { die "bad hnd"; } $ret = PeekNamedPipe($hnd, undef, 0, undef, $TotalBytesAvail, undef); if(!$ret) { my $err = Win32::GetLastError(); die "PNP failed $err $^E"; } if($TotalBytesAvail) { #can safely read }
In Section
Seekers of Perl Wisdom