Win32: How to quit perl script during log off automatically ?

P

Peter Sobisch

Hi folks,

on Unix its a simplest thing, perl do it for me or I can set $SIG{HUP} :)
but, how can I do this in Windows ?

Every time I try to shutdown or log off, pop-up is comming up with
"application doesn't response" and expecting to kill by clicking a
button -> very dirty thing :-/

So, I tried to catch WM_QUERYENDSESSION (using Win32::GUI::Hook), but no
WM_QUERYENDSESSION will be sent to the script (although the script is able
to receive other Window-Messages send by SendMessage).

Is it so, because perl is a "console based application" and windows sends
WM_QUERYENDSESSION + WM_ENDSESSION only to GUI applications ?

I "googled" and found something about SetConsoleCtrlHandler, which should give
similar funcitionality as WM_QUERYENDSESSION mechanism, but in order to set
this, I need to define a callback using Win32::API::Callback in my perl code,
but, this module doesn't work for me at all, it generates segfault every time,
even using the very simple examples from the documentation (nmake test fails
also).

Is there any other simple way to recognize inside of a perl script
that the Windows is shutting down or the user is logging off ?

I run ActivePerl 5.8.8 on W2k/XPpro.

regards,
Peter
 
L

Lambik

Peter Sobisch said:
Hi folks,

on Unix its a simplest thing, perl do it for me or I can set $SIG{HUP} :)
but, how can I do this in Windows ?

Every time I try to shutdown or log off, pop-up is comming up with
"application doesn't response" and expecting to kill by clicking a
button -> very dirty thing :-/

So, I tried to catch WM_QUERYENDSESSION (using Win32::GUI::Hook), but no

You should reveive a WM_CLOSE according to Bill.
 
P

Peter Sobisch

Lambik said:
You should reveive a WM_CLOSE according to Bill.


not really, I'm affraid windows doesn't sent neither WM_CLOSE nor
WM_QUIT because of the same reason of not sending WM_QUERYENDSESSION.

There must be something more in the Win32-universe :)


regards
Peter
 
R

Reinhard Pagitsch

Peter said:
not really, I'm affraid windows doesn't sent neither WM_CLOSE nor
WM_QUIT because of the same reason of not sending WM_QUERYENDSESSION.

There must be something more in the Win32-universe :)

Have you also read the MSDN documentation about SetConsoleCtrlHandler?
The last paragraph say:

The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and
CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off,
or shuts down the system so that the process has an opportunity to clean
up before termination. Console functions, or any C run-time functions
that call console functions, may not work reliably during processing of
any of the three signals mentioned previously. The reason is that some
or all of the internal console cleanup routines may have been called
before executing the process signal handler.

Can you send me the code you are using, maybe I can find it out why the
Win32::API::Callback Module crashes.

regards,
Reinhard
 
P

Peter Sobisch

Reinhard Pagitsch said:
Have you also read the MSDN documentation about SetConsoleCtrlHandler?
The last paragraph say:

The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and
CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off,
or shuts down the system so that the process has an opportunity to clean
up before termination. Console functions, or any C run-time functions
that call console functions, may not work reliably during processing of
any of the three signals mentioned previously. The reason is that some
or all of the internal console cleanup routines may have been called
before executing the process signal handler.

this is the thing I wanted to do but the Win32::API::Callback doesn't
work :-(
But I have a small workaround for now, I wrote a C module where I
register a C-written-callback where I run ExitProcess().
It's dirty to me, because I have no possibility to clean up or do
something else, but, the process really ends on logoff.

Neverthereless, I still interesting in Win32::API::Callback to get it
work, because it would be very useful feature in Win32 enviroment.

I tried to write something similars, but how I mentioned above, I've a
problem to call a perl routine from the C-callback, not even the
simplest one from perlcall manpage worked, I got SEGFAULT every time.

I'm not sure, but could it be a problem calling the call_pv() or call_sv()
from the callback which is launching in another thread ?

MS says the CtrlHandler will be called in separated thread, see
the "HandlerRoutine" in MSDN:

------snip------
Because the system creates a new thread in the process to execute the
handler function, it is possible that the handler function will be
terminated by another thread in the process. Be sure to synchronize
threads in the process with the thread for the handler function.
------snap------
Can you send me the code you are using, maybe I can find it out why the
Win32::API::Callback Module crashes.

just a simple define of a callback:

----snip---
use Win32::API;
use Win32::API::Callback;

my $callback = Win32::API::Callback->new(
sub { my($a, $b) = @_; return $a+$b; },
"NN", "N",
);
----snap---

gives the SEGFAULT and following message written to the console:
"Free to wrong pool 15e2660 not e58b2660, <DATA> line 164."
 
T

Thomas Kratz

Peter said:
----snip---
use Win32::API;
use Win32::API::Callback;

my $callback = Win32::API::Callback->new(
sub { my($a, $b) = @_; return $a+$b; },
"NN", "N",
);
----snap---

gives the SEGFAULT and following message written to the console:
"Free to wrong pool 15e2660 not e58b2660, <DATA> line 164."

Your Win32::API::Callback seems to be broken. The code runs without
errors on my 5.8.8 (windows non ActiveState). Where did you install it from?

Thomas

--
$/=$,,$_=<DATA>,s,(.*),$1,see;__END__
s,^(.*\043),,mg,@_=map{[split'']}split;{#>J~.>_an~>>e~......>r~
$_=$_[$%][$"];y,<~>^,-++-,?{$/=--$|?'"':#..u.t.^.o.P.r.>ha~.e..
'%',s,(.),\$$/$1=1,,$;=$_}:/\w/?{y,_, ,,#..>s^~ht<._..._..c....
print}:y,.,,||last,,,,,,$_=$;;eval,redo}#.....>.e.r^.>l^..>k^.-
 
P

Peter Sobisch

Thomas Kratz said:
Your Win32::API::Callback seems to be broken. The code runs without
errors on my 5.8.8 (windows non ActiveState). Where did you install it from?

I've also ActiveState 5.8.8 Build 817 installed, I got the Win32::API-0.46 from
CPAN and installed it by using Bloodshed Dev-C++ 4.9.9.2 and nmake1.5.

Evereything went well, except the Callback test, which has failed.
Nevertheless I did "nmake install" in order to use the other
Win32::API functionality.

I run Windows XP Pro SP 2.

Regards,
Peter
 
R

Reinhard Pagitsch

Peter said:
this is the thing I wanted to do but the Win32::API::Callback doesn't
work :-(
But I have a small workaround for now, I wrote a C module where I
register a C-written-callback where I run ExitProcess().
It's dirty to me, because I have no possibility to clean up or do
something else, but, the process really ends on logoff.

Neverthereless, I still interesting in Win32::API::Callback to get it
work, because it would be very useful feature in Win32 enviroment.

I tried to write something similars, but how I mentioned above, I've a
problem to call a perl routine from the C-callback, not even the
simplest one from perlcall manpage worked, I got SEGFAULT every time.

I'm not sure, but could it be a problem calling the call_pv() or call_sv()
from the callback which is launching in another thread ?

MS says the CtrlHandler will be called in separated thread, see
the "HandlerRoutine" in MSDN:

------snip------
Because the system creates a new thread in the process to execute the
handler function, it is possible that the handler function will be
terminated by another thread in the process. Be sure to synchronize
threads in the process with the thread for the handler function.
------snap------


just a simple define of a callback:

----snip---
use Win32::API;
use Win32::API::Callback;

my $callback = Win32::API::Callback->new(
sub { my($a, $b) = @_; return $a+$b; },
"NN", "N",
);
----snap---

gives the SEGFAULT and following message written to the console:
"Free to wrong pool 15e2660 not e58b2660, <DATA> line 164."

As Thomas wrote, the Module is broken. I assume to remove it and install
it again. In my environment, Activestate 5.8.8 on XP Sp2, this code
works perfect.

You can download it from http://www.bribes.org/perl/ppm/ (30-Jan-2007)
or Activestate.

Here you can find a list of PPM repositories:
http://win32.perl.org/wiki/index.php?title=PPM_Repositories

regards,
Reinhard
 
L

Lambik

Peter Sobisch said:
not really, I'm affraid windows doesn't sent neither WM_CLOSE nor
WM_QUIT because of the same reason of not sending WM_QUERYENDSESSION.

I hate to state the obvious, but I recon you considered making it a windows
program using win32::gui. It has a getMessage
http://dada.perl.it/gui_docs/Win32_GUI.html#GetMessage_MIN_MAX_



And you could use threads adding a thread which listens to a c program. But
I guess you've already done that. There is always the possibility to make
your own XS module.



#include <windows.h>

#include <stdio.h>



BOOL CtrlHandler( DWORD fdwCtrlType )

{

switch( fdwCtrlType )

{

case CTRL_LOGOFF_EVENT:

Beep( 1000, 200 );

printf( "Ctrl-Logoff event\n\n" );

return FALSE;



case CTRL_SHUTDOWN_EVENT:

Beep( 750, 500 );

printf( "Ctrl-Shutdown event\n\n" );

return FALSE;



default:

return FALSE;

}

}



void main( void )

{

if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) )

{

while( 1 ){ }

}

else

printf( "\nERROR: Could not set control handler");

}
 
P

Peter Sobisch

Reinhard Pagitsch said:
Peter said:
Reinhard Pagitsch said:
Every time I try to shutdown or log off, pop-up is comming up with
"application doesn't response" and expecting to kill by clicking a
button -> very dirty thing :-/
So, I tried to catch WM_QUERYENDSESSION (using Win32::GUI::Hook), but no
You should reveive a WM_CLOSE according to Bill.
not really, I'm affraid windows doesn't sent neither WM_CLOSE nor
WM_QUIT because of the same reason of not sending WM_QUERYENDSESSION.

Have you also read the MSDN documentation about SetConsoleCtrlHandler?
The last paragraph say:

The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and
CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off,
or shuts down the system so that the process has an opportunity to clean
up before termination. Console functions, or any C run-time functions
that call console functions, may not work reliably during processing of
any of the three signals mentioned previously. The reason is that some
or all of the internal console cleanup routines may have been called
before executing the process signal handler.

this is the thing I wanted to do but the Win32::API::Callback doesn't
work :-(
But I have a small workaround for now, I wrote a C module where I
register a C-written-callback where I run ExitProcess().
It's dirty to me, because I have no possibility to clean up or do
something else, but, the process really ends on logoff.

Neverthereless, I still interesting in Win32::API::Callback to get it
work, because it would be very useful feature in Win32 enviroment.

I tried to write something similars, but how I mentioned above, I've a
problem to call a perl routine from the C-callback, not even the
simplest one from perlcall manpage worked, I got SEGFAULT every time.

I'm not sure, but could it be a problem calling the call_pv() or call_sv()
from the callback which is launching in another thread ?

[...]
Can you send me the code you are using, maybe I can find it out why the
Win32::API::Callback Module crashes.

just a simple define of a callback:

----snip---
use Win32::API;
use Win32::API::Callback;

my $callback = Win32::API::Callback->new(
sub { my($a, $b) = @_; return $a+$b; },
"NN", "N",
);
----snap---

gives the SEGFAULT and following message written to the console:
"Free to wrong pool 15e2660 not e58b2660, <DATA> line 164."

As Thomas wrote, the Module is broken. I assume to remove it and install
it again. In my environment, Activestate 5.8.8 on XP Sp2, this code
works perfect.

You can download it from http://www.bribes.org/perl/ppm/ (30-Jan-2007)
or Activestate.

Here you can find a list of PPM repositories:
http://win32.perl.org/wiki/index.php?title=PPM_Repositories

thanks for the link !
Module doesn't crash anymore :)
now I only one step further, but the call I wanted to do fails now
in calling the callback, here the code:

------------------------snip-----------------
use strict;
use Win32::API;
use Win32::API::Callback;

sub handler {
my $type = shift;
print "RECEIVED SIGNAL: $type\n",;
return 1;
}

my $callback =
Win32::API::Callback->new(\&handler, "I", "I" );
my $function =
Win32::API->new('kernel32','SetConsoleCtrlHandler','KI','I');
$function->Call($callback,1);

my $i= 0;
while ($i<2000) {
print ++$i,"\n";
sleep(1); # in this loop press Ctrl+C
}
-----------------------snap----------------------

it crashs now not by defining the callback but
after I press "Ctrl+C" inside the loop :-/

If I do this in XSUB it seems to work, but only to do ExitProcess(),
But I'd like to be able to call a callback.

For comparison here comes my working XS code (with ExitProcess()):

-----------snip------------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "windows.h"
#include "wincon.h"

#define MAX_EVENT CTRL_SHUTDOWN_EVENT
int event[7] = { 0,0,0,0,0,0,0 };

BOOL WINAPI CtrlHandler(DWORD type) {
printf("received: %d\n",type);
if (type > MAX_EVENT)
return FALSE;
if (event[type])
ExitProcess(0);
return FALSE;
}

MODULE = Logoff PACKAGE = Logoff

int
LogoffOnEvent(ev, logoff)
int ev
int logoff
CODE:
int rv;
if (ev > MAX_EVENT) {
rv = -1;
} else {
event[ev] = logoff;
rv = SetConsoleCtrlHandler(CtrlHandler,TRUE);
}
RETVAL = rv;
OUTPUT:
RETVAL
-----------snap------------------

to test this module I use this simple piece of perl code:

-----------snip-----------------
use Logoff;
Logoff::LogoffOnEvent(5,1); # quits after Logoff
Logoff::LogoffOnEvent(0,1); # quits after Ctrl+C

do {
print "sleeping...$i\n"; # try to logoff or Ctrl+C
sleep(1);
} until $i > 10000;
------------snap----------------

the big disadvantage of this is that I have no possibility to clean up
my perl code.

As I wrote before, I tried already to call a perl callback in
CtrlHandler using call_sv() or call_pv(), without any success,
this ends every time with segfault calling the perl code,
the same thing as the perl variant using Win32::API::Callback
also does (ofcourse after I re-installed the Win32::API-0.46
module from http://www.bribes.org/perl/ppm/).

Are there a more restrictions inside a CtrlHandler which disallow to
do something like call a perl callback ?

regards
Peter
 
P

Peter Sobisch

Lambik said:
I hate to state the obvious, but I recon you considered making it a windows
program using win32::gui. It has a getMessage
http://dada.perl.it/gui_docs/Win32_GUI.html#GetMessage_MIN_MAX_

And you could use threads adding a thread which listens to a c program. But
I guess you've already done that. There is always the possibility to make
your own XS module.

#include <windows.h>
#include <stdio.h>

BOOL CtrlHandler( DWORD fdwCtrlType )
{
switch( fdwCtrlType )
{
case CTRL_LOGOFF_EVENT:
Beep( 1000, 200 );
printf( "Ctrl-Logoff event\n\n" );
return FALSE;

case CTRL_SHUTDOWN_EVENT:
Beep( 750, 500 );
printf( "Ctrl-Shutdown event\n\n" );
return FALSE;

default:
return FALSE;
}
}

void main( void )
{
if( SetConsoleCtrlHandler( (PHANDLER_ROUTINE) CtrlHandler, TRUE ) )
{
while( 1 ){ }
}
else
printf( "\nERROR: Could not set control handler");
}

thas is easy ! This works for me already inside a XS to do ExitProcess(),
but my problem is: I'd like to do more than "beep" and "printf".

Please try to call perl code inside CtrlHandler and tellme how :)
Actually I expected I can do this using Win32::API::Callback(),
but I can't get it work :-( See my another posting.

Regards
Peter
 
L

Lambik

Peter Sobisch said:
Please try to call perl code inside CtrlHandler and tellme how :)
Actually I expected I can do this using Win32::API::Callback(),
but I can't get it work :-( See my another posting.

The other posting seem to have more promise. What i sugested isn't all that
either.

use threads;
my $thread = threads->create(sub { &exitNicely if (`code.exe` =~
/Ctrl-Shutdown event/)});
 
R

Reinhard Pagitsch

Peter said:
Reinhard Pagitsch said:
Peter said:
Every time I try to shutdown or log off, pop-up is comming up with
"application doesn't response" and expecting to kill by clicking a
button -> very dirty thing :-/
So, I tried to catch WM_QUERYENDSESSION (using Win32::GUI::Hook), but no
You should reveive a WM_CLOSE according to Bill.
not really, I'm affraid windows doesn't sent neither WM_CLOSE nor
WM_QUIT because of the same reason of not sending WM_QUERYENDSESSION.

Have you also read the MSDN documentation about SetConsoleCtrlHandler?
The last paragraph say:

The system generates CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT, and
CTRL_SHUTDOWN_EVENT signals when the user closes the console, logs off,
or shuts down the system so that the process has an opportunity to clean
up before termination. Console functions, or any C run-time functions
that call console functions, may not work reliably during processing of
any of the three signals mentioned previously. The reason is that some
or all of the internal console cleanup routines may have been called
before executing the process signal handler.

this is the thing I wanted to do but the Win32::API::Callback doesn't
work :-(
But I have a small workaround for now, I wrote a C module where I
register a C-written-callback where I run ExitProcess().
It's dirty to me, because I have no possibility to clean up or do
something else, but, the process really ends on logoff.

Neverthereless, I still interesting in Win32::API::Callback to get it
work, because it would be very useful feature in Win32 enviroment.

I tried to write something similars, but how I mentioned above, I've a
problem to call a perl routine from the C-callback, not even the
simplest one from perlcall manpage worked, I got SEGFAULT every time.

I'm not sure, but could it be a problem calling the call_pv() or call_sv()
from the callback which is launching in another thread ?

[...]

Can you send me the code you are using, maybe I can find it out why the
Win32::API::Callback Module crashes.

just a simple define of a callback:

----snip---
use Win32::API;
use Win32::API::Callback;

my $callback = Win32::API::Callback->new(
sub { my($a, $b) = @_; return $a+$b; },
"NN", "N",
);
----snap---

gives the SEGFAULT and following message written to the console:
"Free to wrong pool 15e2660 not e58b2660, <DATA> line 164."

As Thomas wrote, the Module is broken. I assume to remove it and install
it again. In my environment, Activestate 5.8.8 on XP Sp2, this code
works perfect.

You can download it from http://www.bribes.org/perl/ppm/ (30-Jan-2007)
or Activestate.

Here you can find a list of PPM repositories:
http://win32.perl.org/wiki/index.php?title=PPM_Repositories

thanks for the link !
Module doesn't crash anymore :)
now I only one step further, but the call I wanted to do fails now
in calling the callback, here the code:

------------------------snip-----------------
use strict;
use Win32::API;
use Win32::API::Callback;

sub handler {
my $type = shift;
print "RECEIVED SIGNAL: $type\n",;
return 1;
}

my $callback =
Win32::API::Callback->new(\&handler, "I", "I" );
my $function =
Win32::API->new('kernel32','SetConsoleCtrlHandler','KI','I');
$function->Call($callback,1);

my $i= 0;
while ($i<2000) {
print ++$i,"\n";
sleep(1); # in this loop press Ctrl+C
}
-----------------------snap----------------------

it crashs now not by defining the callback but
after I press "Ctrl+C" inside the loop :-/

Hmm in my case it does not crash but do also nothing. The print in the
handler sub will not be executed. Could it be that if have to do with
threads?
If I do this in XSUB it seems to work, but only to do ExitProcess(),
But I'd like to be able to call a callback.

For comparison here comes my working XS code (with ExitProcess()):

-----------snip------------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "windows.h"
#include "wincon.h"

#define MAX_EVENT CTRL_SHUTDOWN_EVENT
int event[7] = { 0,0,0,0,0,0,0 };

BOOL WINAPI CtrlHandler(DWORD type) {
printf("received: %d\n",type);
if (type > MAX_EVENT)
return FALSE;
if (event[type])
ExitProcess(0);
return FALSE;
}

MODULE = Logoff PACKAGE = Logoff

int
LogoffOnEvent(ev, logoff)
int ev
int logoff
CODE:
int rv;
if (ev > MAX_EVENT) {
rv = -1;
} else {
event[ev] = logoff;
rv = SetConsoleCtrlHandler(CtrlHandler,TRUE);
}
RETVAL = rv;
OUTPUT:
RETVAL
-----------snap------------------

to test this module I use this simple piece of perl code:

-----------snip-----------------
use Logoff;
Logoff::LogoffOnEvent(5,1); # quits after Logoff
Logoff::LogoffOnEvent(0,1); # quits after Ctrl+C

do {
print "sleeping...$i\n"; # try to logoff or Ctrl+C
sleep(1);
} until $i > 10000;
------------snap----------------

the big disadvantage of this is that I have no possibility to clean up
my perl code.

Why not? You call the XS function direct, but if you do it via a .pm
than you can pass to the method a callback function which have to
executed before the XS code, theoretical.
As I wrote before, I tried already to call a perl callback in
CtrlHandler using call_sv() or call_pv(), without any success,
this ends every time with segfault calling the perl code,
the same thing as the perl variant using Win32::API::Callback
also does (ofcourse after I re-installed the Win32::API-0.46
module from http://www.bribes.org/perl/ppm/).

Are there a more restrictions inside a CtrlHandler which disallow to
do something like call a perl callback ?

regards,
Reinhard
 
P

Peter Sobisch

Reinhard Pagitsch said:
thanks for the link !
Module doesn't crash anymore :)
now I only one step further, but the call I wanted to do fails now
in calling the callback, here the code:

------------------------snip-----------------
use strict;
use Win32::API;
use Win32::API::Callback;

sub handler {
my $type = shift;
print "RECEIVED SIGNAL: $type\n",;
return 1;
}

my $callback =
Win32::API::Callback->new(\&handler, "I", "I" );
my $function =
Win32::API->new('kernel32','SetConsoleCtrlHandler','KI','I');
$function->Call($callback,1);

my $i= 0;
while ($i<2000) {
print ++$i,"\n";
sleep(1); # in this loop press Ctrl+C
}
-----------------------snap----------------------

it crashs now not by defining the callback but
after I press "Ctrl+C" inside the loop :-/

Hmm in my case it does not crash but do also nothing. The print in the
handler sub will not be executed. Could it be that if have to do with
threads?

it should at least print the numbers, because it is regular perl code,
thats strange...
If I do this in XSUB it seems to work, but only to do ExitProcess(),
But I'd like to be able to call a callback.
For comparison here comes my working XS code (with ExitProcess()):

-----------snip------------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "windows.h"
#include "wincon.h"

#define MAX_EVENT CTRL_SHUTDOWN_EVENT
int event[7] = { 0,0,0,0,0,0,0 };

BOOL WINAPI CtrlHandler(DWORD type) {
printf("received: %d\n",type);
if (type > MAX_EVENT)
return FALSE;
if (event[type])
ExitProcess(0);
return FALSE;
}

MODULE = Logoff PACKAGE = Logoff

int
LogoffOnEvent(ev, logoff)
int ev
int logoff
CODE:
int rv;
if (ev > MAX_EVENT) {
rv = -1;
} else {
event[ev] = logoff;
rv = SetConsoleCtrlHandler(CtrlHandler,TRUE);
}
RETVAL = rv;
OUTPUT:
RETVAL
-----------snap------------------

to test this module I use this simple piece of perl code:

-----------snip-----------------
use Logoff;
Logoff::LogoffOnEvent(5,1); # quits after Logoff
Logoff::LogoffOnEvent(0,1); # quits after Ctrl+C

do {
print "sleeping...$i\n"; # try to logoff or Ctrl+C
sleep(1);
} until $i > 10000;
------------snap----------------

the big disadvantage of this is that I have no possibility to clean up
my perl code.

Why not? You call the XS function direct, but if you do it via a .pm
than you can pass to the method a callback function which have to
executed before the XS code, theoretical.

the call of Logoff::LogoffOnEvent() is not the problem, this registers only
a C-routine as a callback, which is called later (on event).
This doesn't make any difference.

What I need here is: how to call a perl routine from the CtrlHandler()
in XS. There are several API calls to do this: (perl_)call_pv,
(perl_)call_sv and so on. But none of them seems to run in this
callback.

Regards,
Peter
 
R

Reinhard Pagitsch

Peter said:
Reinhard Pagitsch said:
[...]
http://win32.perl.org/wiki/index.php?title=PPM_Repositories
thanks for the link !
Module doesn't crash anymore :)
now I only one step further, but the call I wanted to do fails now
in calling the callback, here the code:

------------------------snip-----------------
use strict;
use Win32::API;
use Win32::API::Callback;

sub handler {
my $type = shift;
print "RECEIVED SIGNAL: $type\n",;
return 1;
}

my $callback =
Win32::API::Callback->new(\&handler, "I", "I" );
my $function =
Win32::API->new('kernel32','SetConsoleCtrlHandler','KI','I');
$function->Call($callback,1);

my $i= 0;
while ($i<2000) {
print ++$i,"\n";
sleep(1); # in this loop press Ctrl+C
}
-----------------------snap----------------------

it crashs now not by defining the callback but
after I press "Ctrl+C" inside the loop :-/

Hmm in my case it does not crash but do also nothing. The print in the
handler sub will not be executed. Could it be that if have to do with
threads?

it should at least print the numbers, because it is regular perl code,
thats strange...
If I do this in XSUB it seems to work, but only to do ExitProcess(),
But I'd like to be able to call a callback.
For comparison here comes my working XS code (with ExitProcess()):

-----------snip------------------
#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"
#include "ppport.h"
#include "windows.h"
#include "wincon.h"

#define MAX_EVENT CTRL_SHUTDOWN_EVENT
int event[7] = { 0,0,0,0,0,0,0 };

BOOL WINAPI CtrlHandler(DWORD type) {
printf("received: %d\n",type);
if (type > MAX_EVENT)
return FALSE;
if (event[type])
ExitProcess(0);
return FALSE;
}

MODULE = Logoff PACKAGE = Logoff

int
LogoffOnEvent(ev, logoff)
int ev
int logoff
CODE:
int rv;
if (ev > MAX_EVENT) {
rv = -1;
} else {
event[ev] = logoff;
rv = SetConsoleCtrlHandler(CtrlHandler,TRUE);
}
RETVAL = rv;
OUTPUT:
RETVAL
-----------snap------------------

to test this module I use this simple piece of perl code:

-----------snip-----------------
use Logoff;
Logoff::LogoffOnEvent(5,1); # quits after Logoff
Logoff::LogoffOnEvent(0,1); # quits after Ctrl+C

do {
print "sleeping...$i\n"; # try to logoff or Ctrl+C
sleep(1);
} until $i > 10000;
------------snap----------------

the big disadvantage of this is that I have no possibility to clean up
my perl code.

Why not? You call the XS function direct, but if you do it via a .pm
than you can pass to the method a callback function which have to
executed before the XS code, theoretical.

the call of Logoff::LogoffOnEvent() is not the problem, this registers only
a C-routine as a callback, which is called later (on event).
This doesn't make any difference.

What I need here is: how to call a perl routine from the CtrlHandler()
in XS. There are several API calls to do this: (perl_)call_pv,
(perl_)call_sv and so on. But none of them seems to run in this
callback.

Can you try to ask in perl.xs news group? In the libwin32-0.191 and also
in Win32-API-0.46 module I can see that call_pv have to work, but I have
not the time to find out how to make it working in your XS.

regards,
Reinhard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top