grasshopper!!! has asked for the wisdom of the Perl Monks concerning the following question:

How to fork gnuplot, write an initial string to it then background the process. Mean while parent is fetching data and writing to data file.This will run but after one replot gnuplot does not update as if dead.Can run similar program putting gnuplot string(DATA section) in file of its own and spawn gnuplot with this file as its source.Why does this code seem to freeze.How to fork open pipe write to it,exit but leave process running.

#!/usr/bin/perl -w my $pid; $pid = fork; if($pid == 0) { my $pid1 = open(CHILD, "|-", "gnuplot -persist ") or die "Couldn't + fork: $!\n"; local $/=undef; my $plot=<DATA>; print CHILD "$plot\n"; close(CHILD); print"forking\n"; exit; } use LWP::Simple; use Fcntl qw(:DEFAULT :flock); $|++; $SIG{TERM}=sub{print "ok1\n";alarm(0);exit;}; my $url='https://www.cryptonator.com/api/ticker/btc-gbp'; print"ok2\n"; my $interval = 30; # seconds between calls fetch(); sub fetch{ print"ok3\n"; my $replie = get($url); print"$replie \n"; my($a,$b,$c,$d)= $replie =~ /^.+?(\d+\.\d+).+?(\d+\.\d+)?.+?(\d+\ +.\d+).+?(\d+).*$/; $a="not defined" unless defined($a); $b="not defined" unless defined($b); $c="not defined" unless defined($c); $d="not defined" unless defined($d); open(OUT,">>","/home/philip/Desktop/PERLBITCOIN/TICKER/bitgbp1 +.dat") or die "BIT File open error $!\n"; unless (flock(OUT, LOCK_EX|LOCK_NB)) { warn "can't immediately write-lock the file ($!), blocking + ..."; unless (flock(OUT, LOCK_EX)) { die "can't get write-lock on numfile: $!"; } } print OUT "$c,$a,$d\n"; flock(OUT, LOCK_UN) or die "cant unlock file\n"; close(OUT); #print "$c,$a,$d\n"; alarm($interval); }; $SIG{ALRM}=\&fetch; 1 while 1; __DATA__ reset delta_v(x) = ( vD = x - old_v, old_v = x, vD) old_v = NaN unset key set xtics border in scale 0,0 nomirror rotate by -90 offset character + 0,0 autojustify set datafile separator ',' set bmargin at screen 0.15 #set palette defined (100 "red", 200 "green", 300 "blue") set palette defined (-1 "red", 1 "#1B6821") #set palette model RGB defined ( -1 'red', 1 '#006400', 0 'black' ) set cbrange [-1:1] set grid set yrange [*:*] unset colorbox set style fill solid noborder #set xrange [1446061653-946684800:1446064653-946684800] set xdata time set timefmt "%s" set format x "%H:%M" # or anything else set xlabel "time" set xtics autofreq data=system("tail -n 1 '/home/philip/Desktop/PERLBITCOIN/TICKER/bitgbp +1.dat' | awk '{print $0}'") print delta_v(2) plot '< tail -n 40 /home/philip/Desktop/PERLBITCOIN/TICKER/bitgbp1.dat +' using 3:2:((delta_v($2) > 0.0) ? 1 : -1 )with impulses lw 2 palett +e pause 10 reread replot;

Replies are listed 'Best First'.
Re: fork spawn write background problem
by BrowserUk (Patriarch) on Oct 29, 2015 at 15:53 UTC

    The first time gnuplot attempts to draw the graph, it fails because the data file is empty; because the fetch takes longer than starting gnuplots does.

    Hence, gnuplot produces the error message:

    gnuplot> plot '< tail -n 40 c:/test/bitgbp1.dat' using 3:2:((delta_v( +$2) > 0.0) ? 1 : -1 )with impulses lw 2 palette + ^ warning: Skipping data file with no valid points + ^ x range is invalid

    It then pauses for 10 seconds before attempting to reread the file and then replot. By this time the first fetch has completed and the data is available; but gnuplot fails when it attempts to replot, because there hasn't been a previous successful plot!:

    gnuplot> pause 10 {"success":false,"error":"Service temporarily unavailable"} gnuplot> gnuplot> reread gnuplot> gnuplot> replot; ^ no previous plot

    So now gnuplot is no longer running, but the perl script continues to periodically fetch the url and re-write the data file; but nothing is reading it.

    Rearranging your code so that it waits until after the first fetch has been completed and the data written to the file before it spawns gnuplot may get you a bit further.

    Note:I've changed various paths to suit my system, you'll need to set them back:

    #!/usr/bin/perl -w use LWP::Simple; use Fcntl qw(:DEFAULT :flock); my $interval = 30; # seconds between calls my $url='http://www.cryptonator.com/api/ticker/btc-gbp'; # {"success":false,"error":"Service temporarily unavailable"} sub fetch{ print"ok3\n"; my $replie = get($url); print"$replie \n"; my($a,$b,$c,$d)= $replie =~ /^.+?(\d+\.\d+).+?(\d+\.\d+)?.+?(\d+\ +.\d+).+?(\d+).*$/; $a="not defined" unless defined($a); $b="not defined" unless defined($b); $c="not defined" unless defined($c); $d="not defined" unless defined($d); open(OUT,">>","c:/test/bitgbp1.dat") or die "BIT File open err +or $!\n"; unless (flock(OUT, LOCK_EX|LOCK_NB)) { warn "can't immediately write-lock the file ($!), blocking + ..."; unless (flock(OUT, LOCK_EX)) { die "can't get write-lock on numfile: $!"; } } print OUT "$c,$a,$d\n"; flock(OUT, LOCK_UN) or die "cant unlock file\n"; close(OUT); #print "$c,$a,$d\n"; alarm($interval); }; $|++; $SIG{TERM}=sub{print "ok1\n";alarm(0);exit;}; fetch(); my $pid = fork; if($pid == 0) { my $pid1 = open(CHILD, "|-", "C:/Downloaded/gp45-winbin/gnuplot/bi +nary/gnuplot.exe -persist ") or die "Couldn't fork: $!\n"; local $/=undef; my $plot=<DATA>; print CHILD "$plot\n"; close(CHILD); print"forking\n"; exit; } $SIG{ALRM}=\&fetch; print"ok2\n"; sleep; __DATA__ reset delta_v(x) = ( vD = x - old_v, old_v = x, vD) old_v = NaN unset key set xtics border in scale 0,0 nomirror rotate by -90 offset character + 0,0 autojustify set datafile separator ',' set bmargin at screen 0.15 #set palette defined (100 "red", 200 "green", 300 "blue") set palette defined (-1 "red", 1 "#1B6821") #set palette model RGB defined ( -1 'red', 1 '#006400', 0 'black' ) set cbrange [-1:1] set grid set yrange [*:*] unset colorbox set style fill solid noborder #set xrange [1446061653-946684800:1446064653-946684800] set xdata time set timefmt "%s" set format x "%H:%M" # or anything else set xlabel "time" set xtics autofreq data=system("tail -n 1 c:/test/bitgbp1.dat") print delta_v(2) plot '< tail -n 40 c:/test/bitgbp1.dat' using 3:2:((delta_v($2) > 0.0 +) ? 1 : -1 )with impulses lw 2 palette pause 10 reread replot;

    Also note I replaced 1 while 1; which is a busy loop that consumes 100% cpu of the core it runs on with sleep which consumes negligible cpu; and I ditched the completely pointless awl '{print $0}' from the tail commands.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
    In the absence of evidence, opinion is indistinguishable from prejudice.

      Thanks for all the help but does not work on slackware linux.Could be gnuplot, it persists but does not replot

        persists but does not replot

        Sorry, can't help with gnuplot stuff.

        I've tried a few times to make it do stuff I've wanted and failed dismally every time to find the correct combination of arcane voodoo commands.

        I've found it easier to draw what I want manually using GD than fight with gnuplot "manual".


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I knew I was on the right track :)
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: fork spawn write background problem
by Preceptor (Deacon) on Oct 29, 2015 at 13:26 UTC

    Well, the start point would be - gnuplot is doing exactly what you ask it. You fork your code, then send the content of DATA to gnuplot, and then exit. It only does that once, because you only ask it to do it once.

    In doing so, you create a bit of a race condition, as to whether your gnuplot will read your data before you've finished generating it

    But either way - your code sits in a loop generating more data, but you never tell gnuplot to process it again.

      Thank's for your answer but the pause 30 reread replot line's should make gnuplot update automatically.If I put the data in a separate file, say run.gp.And change the child section to code

      exec("gnuplot /home/philip/Desktop/PERLBITCOIN/run.gp"); exit;

      It will run gnuplot and it updates.Gnuplot will not reread and replot if I use the data section instead of the separate file.This is just for interests sake, is there some sort of block on the gnuplot process by using open rather than by exec.

        According to what I read, the reread command is supposed to work with input from STDIN which is what you're using. Could be a gnuplot issue instead of a Perl issue.

        Dum Spiro Spero