Ala Qumsieh said:
GUI
What GUI library are you using? If Tk, then perhaps you can use the
Tk::fileevent method, as described in its pods.
Tk is what I'm using. The GUI part is all done; it's just this last one
command that kicks off another process that is driving me nuts.
What does the second script do? Is there any data that needs to be
passed back to the GUI?
Well, in the *real* application, the secondary script does a lot of stuff.
But as far as the calling GUI code is concerned, it does nothing - it just
goes out and stays out and needs to be killed off at some point via some
method yet to be determined. So, for the purposes of testing, I've just
replaced it with a script that prints out the "spinning text wheel" either
for 30 seconds or so, or (optionally if I uncomment out the commented
lines), forever. This kind of emulates a long-lived process. And since it
won't ever return/terminate (at least not immediately), I can't use
system(), exec() or the "piped process" method since all of those methods
must wait for the secondary application's termination before they can
proceed.
not
I believe on Windows, you can use the command "start prog.pl" to run
your second Perl script in the background.
Do you mean system()?
The perlfork pods claim:
On some platforms such as Windows where the fork() system call is not
available, Perl can be built to emulate fork() at the interpreter
level.
Which Win32 Perl distribution are you using?
Win XP Pro, running Perl ActiveState Perl 5.8.7 (Build 813) - I just
upgraded.
And I
Can you show this code?
If you use open() to create your pipe, then the return value of your
open is the pid of your child process. You can use that to kill() it.
--Ala
Here is the code, stripped down somewhat so that noone has to look at all
the meaningless parts. There are two files: daemon_gui.pl, and test2.pl.
daemon_gui.pl is the Tk-enabled "master" code that sets up the GUI
environment, and kicks off the secondary file (test2.pl) when the "Start
Daemon" button is pressed. As you can see, test2.pl is simply a stub that
"spins its wheels" in the command-line window that daemon_gui.pl is invoked
from (I always like to start the script from a CLI when developing, because
then I can see messages that I would lose if I just double-clicked the file
in Windows Explorer).
So basically, if you invoke daemon_gui.pl (from CLI), the click the Start
button, you'll see the "spinning text" in the CLI. Now what I *want* to
happen is when I press Stop, the secondary script is terminated immediately.
But what is *actually* happening is that the Stop button's actions do not go
into effect until the secondary script has stopped processing.
Some rudimentary debug code in daemon_gui.pl (lines 118 and 129) show me
that the process ID that I am attempting to kill is the same one created
when I invoke the secondary script. Do I need to embed a signal handler
routine in the secondary script or something?
Any ideas, comments, questions, etc?
Thanks for your help
James Calivar
daemon_gui.txt:
==========
#---------------------------#
# initial environment setup
#---------------------------#
use Tk;
use Tk::widgets qw/Dialog/;
use Tk::Balloon;
use subs qw/buildMenuBar finishUp startDaemon stopDaemon/;
use vars qw/$MW $VERSION $pid/;
use strict;
############################################################################
##############
# BEGIN Variable Declarations
#---------------------------------------------------------------------------
-------------#
# version number for internal tracking
$VERSION = '0.97';
#-----------------------------------------------#
# hash used to hold values for all config params
#-----------------------------------------------#
my %config = (
"dbpwd" => undef
);
my @hash_keys = keys %config;
my @hash_vals = values %config;
#-----------------------------------------------#
# hash used to hold popup balloon text msgs
#-----------------------------------------------#
my %configMessages = (
"dbpwd" => "Password for database user account (hidden when typed on
screen)"
);
#-----------------------------------------------#
# hash used to hold handles to Entry widgets
#-----------------------------------------------#
my %configEntry;
#---------------------------------------------------------------------------
-------------#
# END Declarations
############################################################################
##############
############################################################################
##############
# BEGIN Main window geometry setup
#---------------------------------------------------------------------------
-------------#
#-------------------------------------#
# define the main window's attributes
#-------------------------------------#
$MW = MainWindow->new;
$MW->geometry("520x540+0+0");
$MW->title("Daemon GUI $VERSION");
my $menubar = buildMenuBar;
#-------------------------------------------------#
# set up conf.ini variable labels and entry boxes
#-------------------------------------------------#
my $startButton = $MW->Button (-text => "Start Daemon\n", -anchor => 'n',
-foreground => 'black',
-background => 'SeaGreen3',
-activeforeground => 'black',
-activebackground => 'green',
-command => sub {startDaemon})
->place(-anchor=>'nw', -x=>325, -y=>467);
my $stopButton = $MW->Button (-text => "Stop Daemon\n", -anchor => 'n',
-foreground => 'black',
-background => 'salmon1',
-activeforeground => 'white',
-activebackground => 'red',
-command => sub {stopDaemon})
->place(-anchor=>'nw', -x=>425, -y=>467);
my $idx = 0;
foreach my $key (@hash_keys)
{
# draw a label widget that annotates the variable being entered
my $label = $MW->Label(-text => "$key:\n")->place(-anchor =>
'nw', -x=>0, -y=>(10 + $idx*25));
# draw a popover balloon that describes the label widget
my $balloon = $MW->Balloon(-state => 'balloon');
$balloon->attach($label, -balloonmsg => $configMessages{$key}, -initwait
=> 10,
-balloonposition => 'mouse', -state => 'balloon');
# draw an entry widget that accepts input for the variable being entered
# special case for password, which should show up as asteriks
if ($key eq 'dbpwd')
{
$configEntry{$key} = $MW->Entry(-textvariable => \$config{$key}, -show
=> '*')
->place(-anchor=>'nw', -x=>150, -y=>(1
0 + $idx*25));
}
else
{
$configEntry{$key} = $MW->Entry(-textvariable => \$config{$key})
->place(-anchor=>'nw', -x=>150, -y=>(1
0 + $idx*25));
}
$idx++;
}
#---------------------------------------------------------------------------
-------------#
# END Main window geometry setup
############################################################################
##############
############################################################################
##############
# BEGIN Subroutine Definitions
#---------------------------------------------------------------------------
-------------#
#--------------------------------------#
# Start the daemon if all config values
# have been filled out; look for config
# file first, then check entries in GUI
#--------------------------------------#
sub startDaemon {
# kick off daemon
$pid = open DAEMON, "|perl test2.pl";
print ("Process ID created is $pid\n");
} # end startDaemon()
#--------------------------------------#
# commit the changes to the conf file
# (this will be a lot cleaner with the
# config hash)
#--------------------------------------#
sub stopDaemon {
print ("Process ID to kill is $pid\n");
kill 2, $pid or die "Cannot signal $pid with SIGINT: $!";
close DAEMON;
} # end stopDaemon()
#---------------------------------#
# build up the GUI's menu structure
#---------------------------------#
sub buildMenuBar {
# Create the menubar, and File and Quit menubuttons. Note
# that the cascade's menu widget is automatically created.
my $menubar = $MW->Menu;
$MW->configure(-menu => $menubar);
my $file = $menubar->cascade(-label => '~File', -tearoff => 0);
my $help = $menubar->cascade(-label => '~Help', -tearoff => 0);
# Create the menuitems for each menu. First, the File menu item.
$file->command(-label => "Open...", -command => \&open);
$file->separator;
$file->command(-label => "Save...", -command => \&save);
$file->separator;
$file->command(-label => "Quit", -command => \&finishUp);
# Help menuitems (Version and About)
$help->command(-label => 'Version');
$help->separator;
$help->command(-label => 'About');
my $ver_dialog = $MW->Dialog(-title => 'Daemon GUI Utility',
-font=> "Arial 10 normal",
-text=> "Daemon GUI Utility Version
$VERSION",
-buttons => ['OK'],
-bitmap => 'info');
my $about_dialog = $MW->Dialog(-title => 'About Daemon GUI Utility',
-font=> "Arial 10 normal",
-text=> "Daemon GUI Utility Version
$VERSION\n\n\Copywright 2005\n\nDaemon GUI Enterprises, Inc. (LLC)\n\nUse
without explicit permission is strictly prohibited. Violators will be
prosecuted to the fullest extent of the law.",
-buttons => ['OK']);
my $menu = $help->cget('-menu');
$menu->entryconfigure('Version', -command => [$ver_dialog => 'Show']);
$menu->entryconfigure('About', -command => [$about_dialog => 'Show']);
# return the menubar
$menubar;
} # end buildMenuBar()
#--------------------------------------------------#
# retrieve GUI configuration from earlier sessions
#--------------------------------------------------#
sub open {
} # end open()
#--------------------------------------#
# save GUI configuration for later use
#--------------------------------------#
sub save {
} # end save()
#-------------------------------#
# Clean up and exit the program
#-------------------------------#
sub finishUp {
exit;
} # end finishUp()
#---------------------------------------------------------------------------
-------------#
# END Subroutine Definitions
############################################################################
##############
############################################################################
##############
# BEGIN Main Event Processor Loop
#---------------------------------------------------------------------------
-------------#
MainLoop;
#---------------------------------------------------------------------------
-------------#
# END Main Event Processor Loop
############################################################################
##############
test2.pl:
=====
use strict;
my $i = 0;
# while (1) {
for ($i = 0; $i <= 2000000; $i++) {
if (($i % 4) == 0) {
print "|\r";
} elsif (($i % 4) == 1) {
print "/\r";
} elsif (($i % 4) == 2) {
print "-\r";
} else {
# $i = 0;
print "\\\r";
}
# $i++;
}