Skip Menu |

This queue is for tickets about the Tk-Stderr CPAN distribution.

Report information
The Basics
Id: 20718
Status: new
Priority: 0/
Queue: Tk-Stderr

People
Owner: Nobody in particular
Requestors: SREZIC [...] cpan.org
Cc:
AdminCc:

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



Subject: Problems using fork together with Tk::Stderr
Due to the missing thread-safety of Tk it is forbidden to call Tk functions from more than one execution thread, be it a perl thread or a forked process. If a forked process writes something to STDERR in a Tk::Stderr-enabled script, then unfortunately exactly this forbidden thing happens. See the attached script. A possible solution would be to check the pid before PRINTing or PRINTFing in the Tk::Stderr::Handle package. I assume that TIEHANDLE is called very early in the original (parent) process. In this method the pid will be recorded in the Tk::Stderr::Handle object and compared when PRINT is called. The changed methods could look like this: sub Tk::Stderr::Handle::TIEHANDLE { my ($class, $window) = @_; bless { w => $window, pid => $$ }, $class; } sub Tk::Stderr::Handle::PRINT { my $self = shift; if ($self->{pid} != $$) { # child window, use fallback print STDOUT "@_"; } else { my $window = $self->{w}; my $text = $window->Subwidget('text'); $text->insert('end', $_) foreach (@_); $text->see('end'); $window->deiconify; $window->raise; $window->focus; } } In case of a different pid the message will not be written to the Text widget. A better fallback would be to write to STDERR, but this is unfortunately already tied to Tk::Stderr::Handle, hence the usage of STDOUT. Or maybe just untieing STDERR would work? A similar solution would probably be needed for threads, but I don't know much about perl threads. Maybe there's also some kind of thread id which could be compared. Regards, Slaven
Subject: tk-stderr-fork.pl
#!/usr/bin/perl -w use Tk; use Tk::Stderr; $mw = tkinit; $mw->InitStderr; if (fork == 0) { warn "something in child process..."; CORE::exit(0); } warn "something in main process..."; MainLoop; __END__