Perl cron job stays running

Posted by Dylan on Stack Overflow See other posts from Stack Overflow or by Dylan
Published on 2012-09-28T01:55:42Z Indexed on 2012/09/28 21:37 UTC
Read the original article Hit count: 315

I'm currently using a cron job to have a Perl script that tells my Arduino to cycle my aquaponics system and all is well, except the Perl script doesn't die as intended.

Here is my cron job:

*/15 * * * * /home/dburke/scripts/hal/bin/main.pl cycle

And below is my Perl script:

#!/usr/bin/perl -w
# Sample Perl script to transmit number
# to Arduino then listen for the Arduino
# to echo it back

use strict;
use Device::SerialPort;
use Switch;
use Time::HiRes qw ( alarm );
$|++;
# Set up the serial port
# 19200, 81N on the USB ftdi driver
my $device = '/dev/arduino0';
# Tomoc has to use a different tty for testing
#$device = '/dev/ttyS0';

my $port = new Device::SerialPort ($device)
    or die('Unable to open connection to device');;
$port->databits(8);
$port->baudrate(19200);
$port->parity("none");
$port->stopbits(1);

my $lastChoice = ' ';
my $pid = fork();
my $signalOut;
my $args = shift(@ARGV);

# Parent must wait for child to exit before exiting itself on CTRL+C
$SIG{'INT'} = sub {
    waitpid($pid,0) if $pid != 0; exit(0);
};
# What child process should do
if($pid == 0) {
    # Poll to see if any data is coming in
    print "\nListening...\n\n";
    while (1) {
        my $incmsg = $port->lookfor(9);
        # If we get data, then print it
        if ($incmsg) {
            print "\nFrom arduino: " . $incmsg . "\n\n";
        }
    }
}
# What parent process should do
else {
    if ($args eq "cycle") {
        my $stop = 0;
        sleep(1);
        $SIG{ALRM} = sub {
            print "Expecting plant bed to be full; please check.\n";
            $signalOut = $port->write('2'); # Signal to set pin 3 low
            print "Sent cmd: 2\n";
            $stop = 1;
        };
        $signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
        print "Sent cmd: 1\n";
        print "Waiting for plant bed to fill...\n";
        alarm (420);
        while ($stop == 0) {
            sleep(2);
        }
        die "Done.";
    }
    else {
        sleep(1);
        my $choice = ' ';
        print "Please pick an option you'd like to use:\n";
        while(1) {
            print " [1] Cycle  [2] Relay OFF  [3] Relay ON  [4] Config  [$lastChoice]: ";
            chomp($choice = <STDIN>);
            switch ($choice) {
                case /1/ {
                    $SIG{ALRM} = sub {
                        print "Expecting plant bed to be full; please check.\n";
                        $signalOut = $port->write('2'); # Signal to set pin 3 low
                        print "Sent cmd: 2\n";
                    };
                    $signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
                    print "Sent cmd: 1\n";
                    print "Waiting for plant bed to fill...\n";
                    alarm (420);
                    $lastChoice = $choice;
                }
                case /2/ {
                    $signalOut = $port->write('2'); # Signal to set pin 3 low
                    print "Sent cmd: 2";
                    $lastChoice = $choice;
                }
                case /3/ {
                    $signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
                    print "Sent cmd: 1";
                    $lastChoice = $choice;
                }
                case /4/ {
                    print "There is no configuration available yet. Please stab the developer.";
                }
                else {
                    print "Please select a valid option.\n\n";
                }
            }
        }
    }
}

Why wouldn't it die from the statement die "Done.";?

It runs fine from the command line and also interprets the 'cycle' argument fine. When it runs in cron it runs fine, however, the process never dies and while each process doesn't continue to cycle the system it does seem to be looping in some way due to the fact that it ups my system load very quickly. If you'd like more information, just ask.

EDIT: I have changed to code to:

#!/usr/bin/perl -w
# Sample Perl script to transmit number
# to Arduino then listen for the Arduino
# to echo it back

use strict;
use Device::SerialPort;
use Switch;
use Time::HiRes qw ( alarm );
$|++;
# Set up the serial port
# 19200, 81N on the USB ftdi driver
my $device = '/dev/arduino0';
# Tomoc has to use a different tty for testing
#$device = '/dev/ttyS0';

my $port = new Device::SerialPort ($device)
    or die('Unable to open connection to device');;
$port->databits(8);
$port->baudrate(19200);
$port->parity("none");
$port->stopbits(1);

my $lastChoice = ' ';
my $signalOut;
my $args = shift(@ARGV);
# Parent must wait for child to exit before exiting itself on CTRL+C
if ($args eq "cycle") {
    open (LOG, '>>log.txt');
    print LOG "Cycle started.\n";
    my $stop = 0;
    sleep(2);
    $SIG{ALRM} = sub {
        print "Expecting plant bed to be full; please check.\n";
        $signalOut = $port->write('2'); # Signal to set pin 3 low
        print "Sent cmd: 2\n";
        $stop = 1;
    };
    $signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
    print "Sent cmd: 1\n";
    print "Waiting for plant bed to fill...\n";
    print LOG "Alarm is being set.\n";
    alarm (420);
    print LOG "Alarm is set.\n";
    while ($stop == 0) {
        print LOG "In while-sleep loop.\n";
        sleep(2);
    }
    print LOG "The loop has been escaped.\n";
    die "Done.";
    print LOG "No one should ever see this.";
}
else {
    my $pid = fork();
    $SIG{'INT'} = sub {
        waitpid($pid,0) if $pid != 0; exit(0);
    };

    # What child process should do
    if($pid == 0) {
        # Poll to see if any data is coming in
        print "\nListening...\n\n";
        while (1) {
            my $incmsg = $port->lookfor(9);
            # If we get data, then print it
            if ($incmsg) {
                print "\nFrom arduino: " . $incmsg . "\n\n";
            }
        }
    }
    # What parent process should do
    else {
        sleep(1);
        my $choice = ' ';
        print "Please pick an option you'd like to use:\n";
        while(1) {
            print " [1] Cycle  [2] Relay OFF  [3] Relay ON  [4] Config  [$lastChoice]: ";
            chomp($choice = <STDIN>);
            switch ($choice) {
                case /1/ {
                    $SIG{ALRM} = sub {
                        print "Expecting plant bed to be full; please check.\n";
                        $signalOut = $port->write('2'); # Signal to set pin 3 low
                        print "Sent cmd: 2\n";
                    };
                    $signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
                    print "Sent cmd: 1\n";
                    print "Waiting for plant bed to fill...\n";
                    alarm (420);
                    $lastChoice = $choice;
                }
                case /2/ {
                    $signalOut = $port->write('2'); # Signal to set pin 3 low
                    print "Sent cmd: 2";
                    $lastChoice = $choice;
                }
                case /3/ {
                    $signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
                    print "Sent cmd: 1";
                    $lastChoice = $choice;
                }
                case /4/ {
                    print "There is no configuration available yet. Please stab the developer.";
                }
                else {
                    print "Please select a valid option.\n\n";
                }
            }
        }
    }
}

© Stack Overflow or respective owner

Related posts about perl

Related posts about cron