Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation

killing pp exe on windows leaves child running?

by sectokia (Beadle)
on Aug 29, 2019 at 22:18 UTC ( #11105268=perlquestion: print w/replies, xml ) Need Help??

sectokia has asked for the wisdom of the Perl Monks concerning the following question:

Hi wise monks!

I use pp on windows to create an exe.

When running that exe, pp seems to create a child process - which seems to be my perl program.

The problem I have is that if the 'parent' (pp?) is killed off, the child (my program) just keeps on running.

I tried to fix this in my program by getting the ppid, and then doing kill 0, $ppid, to detect if the parent is gone, but because of the way windows maintains the parent ppid in its process table (until all children are gone), kill 0 always returns true, even if the parent is terminated and gone.

I am using websocketd to calling my pp generated exe for each client, and websocketd kills the exe when clients disconnect. But this leaves my program running as a orphan child. Does anyone have any ideas to get around this?


Replies are listed 'Best First'.
Re: killing pp exe on windows leaves child running?
by swl (Priest) on Aug 30, 2019 at 06:58 UTC

    Can you provide more details? i.e. an SSCCE? And details on how you are calling pp?

    I tried running a pp call with a simple infinite loop and it had no issues when I hit control-C in the console. Perhaps that's not analogous to what you are doing, though.

    pp -x -e "while (1) {my $x = 1}"

    When I control-C:

    Can't spawn "C:\berrybrew\5.28.0_64_PDL\perl\bin\perl.exe": No error a +t C:/berrybrew/5.28.0_64_PDL/perl/site/lib/Module/ line 14 +48. Terminate batch job (Y/N)? y

    Some details of what your perl and pp versions are would also be useful. I'm using Strawberry Perl 5.28.0 with pp 1.049 (PAR 1.016).

        Thanks for that. I can replicate the problem on my system when I use the Task Manager to kill the parent process.

Re: killing pp exe on windows leaves child running?
by swl (Priest) on Aug 31, 2019 at 00:45 UTC

    pp calls scandeps, which in turn uses system when it executes the perl script or code. See the source code here.

    This means that the issue can be replicated without pp or scandeps.

    perl -e "system ('perl', '-e', 'while (1) {my $x = 1}'); while (1) {my + $y = 1}"

    In task manager, kill the parent perl process and the child will keep running.

    The reasons for this are best explained by people who know the internals.

Re: killing pp exe on windows leaves child running?
by Anonymous Monk on Aug 30, 2019 at 06:46 UTC

      For C-level Win32::Job improvement (missing parts)

      That would go inside PAR-Packer-1.049\myldr\boot.c and maybe PAR-Packer-1.049\myldr\main.c around "SPAWN"

      With help from Re: Read STDOUT from Win32::Job while process is running, Re^5: Read STDOUT from Win32::Job while process is running,

      A patch

      It compiles with some c/c++ warnings and what knot

      It doesnt add tests for this specific feature

      The existing test suite is failing a few tests ; not sure if related to my patch (my machine is slow)

      ------------------- t/20-pp.t (Wstat: 256 Tests: 34 Failed: 1) Failed test: 28 Non-zero exit status: 1 t/90-rt122949.t (Wstat: 4096 Tests: 109 Failed: 16) Failed tests: 7, 9, 11, 13, 15, 17, 43, 49, 65, 75, 77 79, 81, 83, 91, 93 Non-zero exit status: 16 t/90-rt129312.t (Wstat: 512 Tests: 4 Failed: 2) Failed tests: 3-4 Non-zero exit status: 2 Files=15, Tests=229, 739 wallclock secs ( 0.31 usr + 0.05 sys = 0.36 + CPU) Result: FAIL Failed 3/15 test programs. 19/229 subtests failed. dmake: Error code 255, while making 'test_dynamic'

      Untested if it actually works to end child when parent is killed (test suite still running)

      I tested it, a.exe spawns a.exe, first a.exe is killed, second a.exe doesnt kill itself

      I've no time to debug further, probably fudged something from

      diff -ruN PAR-Packer-1.049/myldr/boot.c PAR-Packer-1.049-new/myldr/boo +t.c --- PAR-Packer-1.049/myldr/boot.c 2019-05-24 14:14:42.000000000 -07 +00 +++ PAR-Packer-1.049-new/myldr/boot.c 2019-09-01 00:28:35.031250000 + -0700 @@ -82,6 +82,8 @@ #endif #ifdef WIN32 +#include "mywin32job.h" + #define unpack_S(p) (*(WORD*)(p)) #define unpack_L(p) (*(DWORD*)(p)) @@ -249,6 +251,7 @@ /* finally spawn the custom Perl interpreter */ argv[0] = my_perl; #ifdef WIN32 + HANDLE killJob = createJobObject("par_daddy_child_ender_PAR_ARGV_ +0"); hinstLib = LoadLibrary("user32"); if (hinstLib != NULL) { ProcAdd = (pALLOW) GetProcAddress(hinstLib, "AllowSetForegrou +ndWindow"); @@ -275,6 +278,7 @@ rc = spawnvp(P_WAIT, my_perl, (char* const*)argv); par_cleanup(stmpdir); + closeHandle( killJob ); exit(rc); #else execvp(my_perl, argv); diff -ruN PAR-Packer-1.049/myldr/main.c PAR-Packer-1.049-new/myldr/mai +n.c --- PAR-Packer-1.049/myldr/main.c 2018-03-31 08:31:17.000000000 -07 +00 +++ PAR-Packer-1.049-new/myldr/main.c 2019-09-01 00:28:01.015625000 + -0700 @@ -4,7 +4,9 @@ #include "perlxsi.c" #include "my_par_pl.c" - +#ifdef WIN32 +#include "mywin32job.h" +#endif /* Workaround for mapstart: the only op which needs a different ppadd +r */ #undef Perl_pp_mapstart #define Perl_pp_mapstart Perl_pp_grepstart @@ -85,6 +87,11 @@ Perl_atfork_unlock); #endif +#ifdef WIN32 + HANDLE killJob = createJobObject("par_daddy_child_ender_PAR_ARGV_ +0"); + assignProcessToJobObject( killJob, GetCurrentProcess() ); +#endif + if (!PL_do_undump) { my_perl = perl_alloc(); if (!my_perl) @@ -148,5 +155,8 @@ perl_free( my_perl ); PERL_SYS_TERM(); +#ifdef WIN32 + closeHandle( killJob ); +#endif return exitstatus; } diff -ruN PAR-Packer-1.049/myldr/mywin32job.h PAR-Packer-1.049-new/myl +dr/mywin32job.h --- PAR-Packer-1.049/myldr/mywin32job.h 1969-12-31 16:00:00.0000000 +00 -0800 +++ PAR-Packer-1.049-new/myldr/mywin32job.h 2019-09-01 00:26:06.609 +375000 -0700 @@ -0,0 +1,25 @@ +/* 2019-09-01-00:16:03 Anonymous Monk */ +#define _WIN32_WINNT 0x0500 +#include <windows.h> + +#ifndef JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE + #define JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE 0x2000 +#endif + +int createJobObject( char *name ) { + HANDLE job; + JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0, }; + jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_ +JOB_CLOSE; + job = (int)CreateJobObjectA( NULL, name ); + SetInformationJobObject( job, 9, &jeli, sizeof(jeli) ); + return job; +} + +int assignProcessToJobObject( int job, int pid ) { + HANDLE hProc = OpenProcess( PROCESS_SET_QUOTA |PROCESS_TERMINATE, + 0, pid ); + return (int)AssignProcessToJobObject( job, hProc ); +} + +int closeHandle( int handle ) { + return (int)CloseHandle( (HANDLE)handle ); +}


        I think its not working cause it uses  rc = spawnvp(P_WAIT, my_perl, (char* const*)argv);

        which ends up being

        DllExport int win32_spawnvp(int mode, const char *cmdname, const char *const *argv)
        from perl\win32\win32.c

        which ends up using CREATE_NEW_PROCESS_GROUP;

        So what needs done is copy/modify win32_spawnvp() or use CreateProcess directly ... to add  JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE

        Too much blind experimenting for me at the moment

        Simply copy/pasting do_spawnvp_handle doesnt compile :/

Re: killing pp exe on windows leaves child running? ( IsParParentAlive )
by Anonymous Monk on Sep 01, 2019 at 02:59 UTC

      Portable version using P9Y::ProcessTable ... it works on win32 , probably works on other OS if par works the same there

      BEGIN { my $PAR_PROGNAME = "$ENV{PAR_TEMP}\\$ENV{PAR_ARGV_0}.exe"; ## hack use P9Y::ProcessTable(); my $perl_process = P9Y::ProcessTable->process; my $parentpid = $perl_process->ppid; my $ExecutablePath = $perl_process->{exe}; undef $perl_process ; no P9Y::ProcessTable(); sub IsParParentAlive { ( $PAR_PROGNAME eq $ExecutablePath ## doublecheck or $ENV{PAR_SPAWNED} ) and kill 0, $parentpid; } }
Re: killing pp exe on windows leaves child running?
by Anonymous Monk on Aug 31, 2019 at 18:42 UTC

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11105268]
Approved by Athanasius
Front-paged by Corion
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (2)
As of 2021-07-27 19:52 GMT
Find Nodes?
    Voting Booth?

    No recent polls found