This originated on the fink-beginners mailing list:
The sequence of commands
> load '< echo "plot sin(x)"'
> load '< echo "plot cos(x)"'
works correctly on MacOSX 10.5: first the sin(x) plot is drawn and then it changes to the cos(x) plot.
On MacOSX 10.6 and 10.7 only the first plot is shown. Subsequent load '<...' commands have no effect.
The reason for this is a bug in the gnuplot sources:
The implementation of the load command in command.c uses misc.c:loadpath_fopen() which opens a pipe using popen(). It then runs misc.c:load_file() which closes the stream via lf_pop(). In misc.c:lf_pop(), the stream is closed using fclose(), which is incorrect. It should use pclose().
Apparently, some OSes like MacOSX 10.5 silently ignore this bug.
It is still visible, though: Each load '<...' command spawns a new /bin/sh process that lives until gnuplot exits.
On MacOSX 10.6 and 10.7, subsequent load '<...' commands also spawn new /bin/sh processes, but apparently their output is not taken into account (buffering effect?) until a pclose() closes the previous popen() call.
The following patch (against gnuplot-4.4.4) solves the problem for me on MacOSX 10.7:
--- src/misc.c~ 2012-01-06 12:34:07.000000000 +0100
+++ src/misc.c 2012-01-06 12:34:57.000000000 +0100
@@ -303,3 +303,3 @@
*/
- (void) fclose(lf->fp);
+ if (pclose(lf->fp)) (void) fclose(lf->fp);
}
Thank you for the bug report and the detailed analysis.
Your fix does seem to work under linux as well, but I worry that on some platforms first calling pclose on what is normally a real file might cause more problems than just an nonzero return code. Also pclose() can return a non-zero value if the child process has disappeared, in which case following it with a call to fclose() is probably not a great idea. But maybe I worry too much :-)
My patch was only meant for proving the analysis.
I imagine that the real patch would be more elaborate, with #ifdef PIPES or something, like what is done in the implementation of the 'save' command in command.c.
if (lf->name[0] == '<')
pclose(lf->fp);
else
....