Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Timeouts with the System call? 2

Status
Not open for further replies.

BMO

Programmer
Aug 20, 2001
7
0
0
GB
Is there a timeout option with the "system" call so that if the required system call doesn't happen within a specifed time, the perl script continues executing at the line after the "system" call? The problem I'm having is that I'm executing an RCOM command with Perl's "system" to a Psion workabout that does not exist in its holster. It is currently just hanging until "system" can successfully execute the RCOM command ie until I put a Psion into its holster. I hope this makes sense!

TIA
 
The system function waits for the command to return. Two ways to timeout on a system call are to execute the system call in the background and to execute the system call from a child process.



 
Thanks raider2001. As I'm new to Perl, does this mean writing another Perl script with the main one calling another one that contains the "system" command? Do you know of any sites which contain examples of this procedure? I can't seem to find one which offers examples of how to do things!

Regards

BMO
 
# start a system process in the background

# the parent and child processes both run at
# the same time
if(my $pid = fork()){
[tab]# this is the parent process
[tab]# do some other stuff
} else {
[tab]# this is the child process
[tab]system('big_long_command');
[tab]exit 0;
}
# this is still the parent process
Mike
michael.j.lacey@ntlworld.com
Email welcome if you're in a hurry or something -- but post in tek-tips as well please, and I will post my reply here as well.
 
"does this mean writing another Perl script
with the main one calling another one that contains the
"system" command?"


Well....Sort of.....
If you want to put a timer on the system call, then ...........
The 'system' function will not return control of the running
script back to the script until the system call finishes.
Consequently, you need to be able to fork a child process to
go off and do the work, immediately returning control to
the parent process, and then mind the child process. If you
are new to Perl, then this might make your head swim a little.
The code below is a simple (maybe to simple) example of
forking two child processes. The first is used to try to do
some real work( in this case counting up to the value of
$duration). The second simply waits a period of time (5 sec)
and then tries to kill the previous child. The forking is
done with this syntax,

$pid = open(PIPE_NAME,"-|");

HuH? - That syntax spawns a child process and returns the
process ID of the child to the parent. In the child, $pid is
null. You end up with two nearly identical copies of the code
running at the same time. The only difference is the $pid var
which is populated in the parent and is null in the child.
STDOUT from the child goes back to the HANDLE in the parent.
You must 'exit' out of the child or it will continue right along
just like the parent.

Code:
#!/usr/local/bin/perl
unless ($duration = $ARGV[0]) { $duration = 8; }

# set autoflush to on to get immediate results from children.
$| = 1;

# fork a child to do the work
$pid = (open(ONE, "-|"));

# $pid exists - this is the parent process
if ($pid)
	{
	# spawn another process to kill the previous
	# child if it lasts to long.
	&spawn_timer($pid);

	# Listen to the pipe from the first child for 
	# the results of what ever you asked it to do.
	while (<ONE>) { print; }
	}
$| = 0; # set AutoFlush back to its default.

# $pid is null 
# this is a child process that needs to be timed/killed
if (!($pid)) 
	{
	for (1..$duration) 
		{
		print &quot;$_\n&quot;;
		sleep(1);
		# You would not want to sleep.  Instead, you would
		# want your system call here.
		# system command, arg1, arg2;
		}
	# exit out here for child - you don't want it to 
	# continue with any code that might follow this 
	# if (!($pid)) block.
	exit;
	}

#----------------------------------------------------------
sub spawn_timer
{
# open/fork a child to time the previously opened child process.
$timer = (open(TIMER, &quot;-|&quot;));
# we now have three copies of the code running.
# we don't care if $time exists indicating a parent

# $timer is null - this must the child
if (!($timer))
	{ 
	sleep(5);
	kill 1,$sibling;
	exit;
	}
}

This is very crude in the world of inter-process control(IPC).
The topic of IPC is beyond what can be dealt with here without
you first doing a little reading and playing. If you want to
get a little more sophisticated with this stuff you will need
to do some reading on SIGNALs, what they are, how to use them,
and such.

[I can't believe there is not a module that will make this
a little more straight forward.... but I have not gone looking,
yet.]


HTH


keep the rudder amid ship and beware the odd typo
 
Thanks very much for taking the time to help. It seems that RCOM does not release the serial port after its process has been killed off. This causes me a problem as when control goes back to the parent process, Perl complains that it cannot access the serial port to go to the next Psion hand held. :-(
 
hhmmmmm .....<ponder...ponder>
Sorry, I've never played with manipulating serial ports with Perl. I'm sure you can do, 'just never been there to figure out how.

???? Does the RCOM API allow for checking that a Psion is available before connecting.... something similar to what ping is in the more general sense????

If not, you might try to find a module that will let you get at the serial port directly and clear it in the event that a child process has been killed.

Good Luck


keep the rudder amid ship and beware the odd typo
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top