Skip Menu |

This queue is for tickets about the Win32-Console CPAN distribution.

Report information
The Basics
Id: 33513
Status: open
Priority: 0/
Queue: Win32-Console

People
Owner: Nobody in particular
Requestors: yon.ar.chall [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: (no value)
Broken in: (no value)
Fixed in: (no value)



Subject: Handle to std channel broken by the DESTROY method of Win32::Console
Perl version : ActivePerl 5.8.8 (MSWin32-x86-multi-thread), build 819 OS : Microsoft Windows XP Professional Module version : Win32::Console 0.07 PROBLEM: The handle to standard channel is broken if the DESTROY method of Win32::Console is (implicitly) invoked. CODE TO REPRODUCE THE PROBLEM: _CODE_BEGIN_ use Win32::Console; { Win32::Console->new(Win32::Console::STD_OUTPUT_HANDLE()); } # note that the Win32::Console "new" call is enclosed in a block print "Hello\n"; _CODE_END_ SYMPTOM: No "Hello" is displayed. WHO'S GUILTY ?: The guilty party is the DESTROY method of Win32::Console (implicitly invoked at the end of the enclosing block), which calls the Win32 API CloseHandle. This guilt can be revealed with the simple following code : _CODE_BEGIN_ use Win32API::File; Win32API::File::CloseHandle(Win32API::File::GetOsFHandle(STDOUT)); print "Hello\n"; _CODE_END_ EXPLANATION ATTEMPT: The Win32::Console DESTROY method closes the file handle at the Windows layer, and doesn't worry about the associated file handle at the Perl layer (STDOUT in the present case). So finally, STDOUT points to a closed Windows native file handle. WORKAROUND: After the DESTROY method has been invoked (might need a fine analysis on some existing code), closing (explicitly) the Perl file handle, and re-opening it. e.g., to re-open the standard channels on the console (classical use) : for STDOUT or STDERR : close STDxxx; open STDxxx, '>CONOUT$'; for STDIN : close STDIN; open STDIN, '+<CONIN$'; CORRECTION SUGGESTION: Win32::Console does not create (*) - nor open, nor duplicate - some Windows file handle... so, why closing it in the DESTROY method ? (*) In opposition to what is written in the Win32::Console documentation for the "new" method : the "new" method actually simply "gets" a standard handle, it does not "creates" it, does it ? P.S.: I only talked about the standard channel mode of Win32::Console. Is the console screen buffer mode also concerned ? I don't know.
Subject: Proposed patch
From: Richard.Burkert [...] gmail.com
The following patch simply sets a flag in new indicating if the handle is a standard handle, and then modifies DESTROY to only close the handle if that flag is not set.
--- Console.pm.old Mon Sep 19 12:49:36 2005 +++ Console.pm Fri Mar 13 14:31:25 2009 @@ -135,6 +135,7 @@ or $param1 == constant("STD_ERROR_HANDLE", 0))) { $self->{'handle'} = _GetStdHandle($param1); + $self->{'handle_is_std'} = 1; } else { $param1 = constant("GENERIC_READ", 0) | constant("GENERIC_WRITE", 0) unless $param1; @@ -600,7 +601,7 @@ sub DESTROY { #============ my($self) = @_; - _CloseHandle($self->{'handle'}); + _CloseHandle($self->{'handle'}) unless $self->{'handle_is_std'}; } #######################################################################
On Fri Mar 13 15:00:36 2009, rrburkert wrote: Show quoted text
> The following patch simply sets a flag in new indicating if the handle > is a standard handle, and then modifies DESTROY to only close the handle > if that flag is not set.
Hi, any chance of getting this patch rolled into the main distribution?
RT-Send-CC: jand [...] activestate.com, a.calpini [...] romagiubileo.it
This issue also causes problems with the use of threads. If a Win32::Console object exists and a thread is then joined (or detached) the cloned Win32::Console object in the thread calls the DESTROY method and renders the Console unuseable thereafter. The following snippet illustrates; again the "Hello" is not displayed. _CODE_BEGIN_ use threads; use Win32::Console; Win32::Console->new(Win32::Console::STD_OUTPUT_HANDLE()); $myThread = threads->create( sub { return } ); $myThread->join(); print "Hello\n"; _CODE_END_ I'm using: Perl version : ActivePerl v5.12.3 (MSWin32-x86-multi-thread), build 1204 OS : Microsoft Windows XP Professional Module version : Win32::Console 0.09 I had initally fixed this by inserting this line in Console.pm, just before sub AUTOLOAD: sub CLONE_SKIP { 1 } # Make module thread safe by not cloning it into child threads This ensures that the DESTROY method is only called once per object (and not every time a clone of the object is destroyed in a thread). In fact what this does is that it prevents any cloning of Win32::Console into child threads, which works for me. However the fix suggested in this bug report by Richard Burkert also fixes the problem and is more general. This bug report was raised on module version 0.07 five years ago and now we are on 0.09. Any chance this can be fixed in a new version ? Thanks