Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

alarm not working with Windows XP #7035

Open
p5pRT opened this issue Jan 13, 2004 · 9 comments
Open

alarm not working with Windows XP #7035

p5pRT opened this issue Jan 13, 2004 · 9 comments

Comments

@p5pRT
Copy link

p5pRT commented Jan 13, 2004

Migrated from rt.perl.org#24892 (status was 'open')

Searchable as RT24892$

@p5pRT
Copy link
Author

p5pRT commented Jan 13, 2004

From awu@qualcomm.com

Hi,

I have a perl script for Windows XP using alarm, but the alarm doesn't
seem to work. I found [perl #24739] is another discussion for this
problem. However, Terry Grieb said it supports to work for XP. I'm
enclosing a segment of my code that setup & catch the alarm signal.
Would you please take a look and let me know if I have a bug in my code,
or alarm doesn't work for Windows XP either. Thank you very much!!!

==== cut sample code =====

$SIG{ALRM} = sub {

  close SOCK;

  print "timeout\n";

  die;

};

.... Setup socket ... (this part work)

alarm 10; # alarm wait for 10 seconds.

.... Write to the socket & wait for reply from the socket, but the
socket never replied, and the $SIG{ALRM} subroutine never was called.

==== end sample code ====

@p5pRT
Copy link
Author

p5pRT commented May 4, 2004

From guest@guest.guest.xxxxxxxx

I have found similiar behavior on Windows 2000 machine using <STDIN> as
the delay factor, Perl 5.8.4.

$SIG{ALRM} = sub { die "Alarm!\n" };

alarm 2;

my $ans = <STDIN>;
chomp($ans);

print "No alarm.\n";

This may help find the root cause of the problem, since it's a simpler
test case.

@p5pRT
Copy link
Author

p5pRT commented May 4, 2004

The RT System itself - Status changed from 'new' to 'open'

@p5pRT
Copy link
Author

p5pRT commented May 4, 2004

From awu@qualcomm.com

Thanks!!

-----Original Message-----
From​: Guest via RT [mailto​:perlbug-followup@​perl.org]
Sent​: Tuesday, May 04, 2004 12​:05 PM
To​: Wu, Ann
Subject​: [perl #24892] alarm not working with Windows XP (and win2000)

I have found similiar behavior on Windows 2000 machine using <STDIN> as
the delay factor, Perl 5.8.4.

$SIG{ALRM} = sub { die "Alarm!\n" };

alarm 2;

my $ans = <STDIN>;
chomp($ans);

print "No alarm.\n";

This may help find the root cause of the problem, since it's a simpler
test case.

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2012

From @Hugmeir

On Tue May 04 12​:05​:11 2004, guest wrote​:

I have found similiar behavior on Windows 2000 machine using <STDIN> as
the delay factor, Perl 5.8.4.

$SIG{ALRM} = sub { die "Alarm!\n" };

alarm 2;

my $ans = <STDIN>;
chomp($ans);

print "No alarm.\n";

This may help find the root cause of the problem, since it's a simpler
test case.

I just built Perl on WinXP, and while this is still present, perlport's
note of alarm() somewhat explains what's going on. But in any case,
could a Windows porter take a look at this?

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2012

From @bulk88

On Sun Apr 29 18​:20​:57 2012, Hugmeir wrote​:

I just built Perl on WinXP, and while this is still present, perlport's
note of alarm() somewhat explains what's going on. But in any case,
could a Windows porter take a look at this?

  ntdll.dll!_KiFastSystemCallRet@​0()
  ntdll.dll!_ZwRequestWaitReplyPort@​12() + 0xc
  ntdll.dll!_CsrClientCallServer@​16() + 0x57
  kernel32.dll!_ReadConsoleInternal@​32() + 0x1c8
  kernel32.dll!_ReadConsoleA@​20() + 0x3b
  kernel32.dll!_ReadFile@​20() + 0xa5

msvcr71.dll!_read_lk(int fh=0, void * buf=0x00834074, unsigned int
cnt=4096) Line 154 + 0x15 C
  msvcr71.dll!_read(int fh=0, void * buf=0x00834074, unsigned int
cnt=4096) Line 75 + 0xc C
  perl512.dll!win32_read(int fd=0, void * buf=0x00834074, unsigned int
cnt=4096) Line 3746 + 0x12 C
  perl512.dll!PerlLIORead(IPerlLIO * piPerl=0x00285dbc, int handle=0,
void * buffer=0x00834074, unsigned int count=4096) Line 1049 + 0x11 C++
  perl512.dll!PerlIOUnix_read(interpreter * my_perl=0x003940dc, _PerlIO
* * f=0x00823474, void * vbuf=0x00834074, unsigned int count=4096) Line
2671 + 0x22 C
  perl512.dll!Perl_PerlIO_read(interpreter * my_perl=0x003940dc, _PerlIO
* * f=0x00823474, void * vbuf=0x00834074, unsigned int count=4096) Line
1627 + 0x3e C
  perl512.dll!PerlIOBuf_fill(interpreter * my_perl=0x003940dc, _PerlIO *
* f=0x008232f8) Line 3882 + 0x1b C
  perl512.dll!Perl_PerlIO_fill(interpreter * my_perl=0x003940dc, _PerlIO
* * f=0x008232f8) Line 1723 + 0x36 C
  perl512.dll!PerlIOBase_read(interpreter * my_perl=0x003940dc, _PerlIO
* * f=0x008232f8, void * vbuf=0x0006d92b, unsigned int count=1) Line
2131 + 0xd C
  perl512.dll!PerlIOBuf_read(interpreter * my_perl=0x003940dc, _PerlIO *
* f=0x008232f8, void * vbuf=0x0006d92b, unsigned int count=1) Line
3903 + 0x15 C
  perl512.dll!Perl_PerlIO_read(interpreter * my_perl=0x003940dc, _PerlIO
* * f=0x008232f8, void * vbuf=0x0006d92b, unsigned int count=1) Line
1627 + 0x3e C
  perl512.dll!PerlIO_getc(_PerlIO * * f=0x008232f8) Line 5081 + 0x13 C
  perl512.dll!Perl_sv_gets(interpreter * my_perl=0x003940dc, sv * const
sv=0x0082bd2c, _PerlIO * * const fp=0x008232f8, long append=0) Line
7196 + 0x9 C
  perl512.dll!Perl_do_readline(interpreter * my_perl=0x003940dc) Line
1675 + 0x15 C
  perl512.dll!Perl_pp_readline(interpreter * my_perl=0x003940dc) Line
323 + 0x9 C
  perl512.dll!Perl_runops_debug(interpreter * my_perl=0x003940dc) Line
2049 + 0xd C
  perl512.dll!S_run_body(interpreter * my_perl=0x003940dc, long
oldscope=1) Line 2308 + 0xd C
  perl512.dll!perl_run(interpreter * my_perl=0x003940dc) Line 2233 + 0xd C
  perl512.dll!RunPerl(int argc=2, char * * argv=0x00282510, char * *
env=0x002828f0) Line 270 + 0x9 C++
  perl.exe!main(int argc=2, char * * argv=0x00282510, char * *
env=0x00282d40) Line 23 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23

The console is synchronous IO. OS calls can not be interrupted. There is
no concept of signals on Windows except for "Alertable IO"(TM). Whatever
the fix, it won't be through the CRT. PeekConsoleInput
http​://msdn.microsoft.com/en-us/library/windows/desktop/ms684344%28v=vs.85%29.aspx
might be related. Quickly thinking over it, the only way to implement
alarm on windows for IO is perform all IO as async IO but with
WaitForSingleObjectEx (alertable on), and a alertable timer
SetWaitableTimer
http​://msdn.microsoft.com/en-us/library/windows/desktop/ms686289%28v=vs.85%29.aspx
to create the alarm interrupt. Or just use WFSO on the async file handle
with the timer on WFSO set to the alarm interval. It is absolutely
possible. The alertable way I described above is probably how Interix
does it.

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2012

From @ikegami

On Mon, Apr 30, 2012 at 11​:56 AM, bulk 88 via RT
<perlbug-followup@​perl.org>wrote​:

The console is synchronous IO. OS calls can not be interrupted. There is
no concept of signals on Windows except for "Alertable IO"(TM). Whatever
the fix, it won't be through the CRT.

But why isn't the "signal" raised after readline returns?

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2012

From @bulk88

On Mon Apr 30 11​:03​:52 2012, ikegami@​adaelis.com wrote​:

But why isn't the "signal" raised after readline returns?
You are making a good point. I dont know.

I modded the script to,
_____________________
$SIG{ALRM} = sub { die "Alarm!\n" };

alarm 2;
system("pause");

my $ans = <STDIN>;
chomp($ans);

print "No alarm.\n";
_____________________
I set a couple C breakpoints.
The WM_TIMER got processed not in runops async check but in pp_system's
async check. With the original script, with the same breakpoints, I
never saw a WM_TIMER.

  perl512.dll!win32_message_window_proc(void * hwnd=0x00120ad0, unsigned
int msg=0x00000113, unsigned int wParam=0x00000001, long
lParam=0x00000000) Line 4913 C
  user32.dll!_InternalCallWinProc@​20() + 0x28
  user32.dll!_UserCallWinProcCheckWow@​32() + 0xb7
  user32.dll!_DispatchMessageWorker@​8() + 0xdc
  user32.dll!_DispatchMessageA@​4() + 0xf
  perl512.dll!win32_async_check(interpreter * my_perl=0x003940dc)
Line 2150 C

perl512.dll!win32_msgwait(interpreter * my_perl=0x003940dc, unsigned
long count=0x00000001, void * * handles=0x0006f998, unsigned long
timeout=0xffffffff, unsigned long * resultp=0x00000000) Line 2195 + 0x9 C
  perl512.dll!win32_spawnvp(int mode=0x00000000, const char *
cmdname=0x00822f44, const char * const * argv=0x00822e6c) Line 4249 +
0x19 C
  perl512.dll!do_spawn2(interpreter * my_perl=0x003940dc, const char *
cmd=0x00832c74, int exectype=0x00000002) Line 784 + 0x11 C
  perl512.dll!Perl_do_spawn(interpreter * my_perl=0x003940dc, char *
cmd=0x00832c74) Line 820 + 0xf C
  perl512.dll!Perl_pp_system(interpreter * my_perl=0x003940dc) Line
4277 + 0x5e C
  perl512.dll!Perl_runops_debug(interpreter * my_perl=0x003940dc) Line
2049 + 0xd C
  perl512.dll!S_run_body(interpreter * my_perl=0x003940dc, long
oldscope=0x00000001) Line 2308 + 0xd C
  perl512.dll!perl_run(interpreter * my_perl=0x003940dc) Line 2233 + 0xd C
  perl512.dll!RunPerl(int argc=0x00000002, char * * argv=0x00282510,
char * * env=0x002828f0) Line 270 + 0x9 C++
  perl.exe!main(int argc=0x00000002, char * * argv=0x00282510, char * *
env=0x00282d40) Line 23 + 0x12 C
  perl.exe!mainCRTStartup() Line 398 + 0xe C
  kernel32.dll!_BaseProcessStart@​4() + 0x23

I'm predicting right now the bug is that there is no way to tell perl to
check the Win32 Msg Queue by sending a message. The CRT signals run in a
separate CRT made thread, and set the sig_pending flag last I remember.

#define WIN32_POLL_INTERVAL 32768
#define PERL_ASYNC_CHECK() if (w32_do_async || PL_sig_pending)
win32_async_check(aTHX)
______________________
later
______________________
#define w32_do_async (w32_poll_count++ > WIN32_POLL_INTERVAL)

I think this might be related to having to do 32K Perl OPs before a
WM_TIMER can be processed. I would have to do some testing to confirm
this. How to fix this? I propose switching to Kernel Timers
(CreateWaitableTimer) rather than GUI Timers and have the Kernel Timers
run in a separate OS thread and pretend to be CRT signals the way CRT
signals currently run (and cause race crashes on all perls see
https://rt-archive.perl.org/perl5/Ticket/Display.html?id=101072 ).

@p5pRT
Copy link
Author

p5pRT commented Apr 30, 2012

From @bulk88

Yep, I was right. This script does the alarm handler after pressing enter.
_________________________________________________________
$SIG{ALRM} = sub { die "Alarm!\n" };

alarm 2;

my $ans = <STDIN>;
chomp($ans);

while($i < 4000000000) {
  $i++;
}
print "No alarm.\n";
_________________________________________________________
C​:\Documents and Settings\Owner\Desktop>perl t1.pl

Alarm!

C​:\Documents and Settings\Owner\Desktop>
_________________________________________________________
It could also be fixed by tossing a ton of async_checks in all IO
opcodes just as its done today with pp_system. I'm done here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants