I'm new to working with pipes, so I don't know whether the following is expected behaviour or a bug on the part of an application.
Since Version 0.47, Inkscape provides a non-GUI interactive shell mode of operation. I am trying to time the program's performance in converting SVG files to PNG images and compare this to other apps. Inkscape expects a line of optional arguments and a file name to be delivered to its command prompt. (see the bottom part of Chapter 24. Using the Command Line for an example how it works) I am using a named pipe for delivering these lines. My benchmarking scripts are these:
svgbench.sh
#!/bin/bash
export BASEDIR=~/PNGs
export SVGDIR=$BASEDIR/svg
export SCRDIR=$BASEDIR/scripts
export WIDTH=600
mkfifo in.fifo
mkfifo out.fifo
inkscape --shell <in.fifo >>out.fifo 2>>$SCRDIR/error &
# start Inkscape in shell mode
# and link stdin and stdout to named pipes
i=1
while [ $i -le 5 ] # multiple runs through all tested apps
do
echo "Inkscape-shell" >>$SCRDIR/error # time Inkscape
/usr/bin/time --format 'Inkscape-shell %e\t%U\t%S' -a --output=$SCRDIR/times $SCRDIR/inkscape-shell.sh
echo "Rsvg" >>$SCRDIR/error # time Gnome's librsvg
/usr/bin/time --format 'rsvg %e\t%U\t%S' -a --output=$SCRDIR/times $SCRDIR/rsvg.sh
echo "" >> $SCRDIR/times
i=`expr $i + 1`
done
echo "quit" >> in.fifo # quit Inkscape
rm in.fifo
rm out.fifo
inkscape-shell.sh
#!/bin/bash
for TESTFILE in `ls $SVGDIR` # get a list of test files
do
echo $TESTFILE " ">>$SCRDIR/error
OUTFILE=$(basename $TESTFILE .svg).png
TESTFILE=$SVGDIR/$TESTFILE
echo "-w $WIDTH -y 0.0 -e $BASEDIR/inkscape1/$OUTFILE $TESTFILE"
# command line for Inkscape
read -sd ">" < out.fifo # wait until input prompt gets thrown back
done >> in.fifo
echo >>$SCRDIR/error
As you can see, the pipe Inkscape gets its commands from is accessed consecutively from different processes (one for every test loop, and the 'quit' command), and there are times when the pipe in.fifo is not connected to any file descriptor. Whenever this happens, Inkscape quits, even if no explicit quit command is given.
I have tracked this behaviour back to this: man pipe(7) states "If all file descriptors referring to the write end of a pipe have been closed, then an attempt to read from the pipe will see end-of-file (read will return 0)." Looking closely at the accordant source code of Inkscape, I think what happens is that
- stdin is read continuously in a loop
- fgets() in line 01059 means that an EOF will cause the loop and consequently the programm to quit.
Now my question: is this the expected behaviour of an interactive shell program, or should it be perceived as a bug?
And if it is to be expected, how could I achieve a timed execution of inkscape-shell.sh without forking to a new process? Are there other ways to feed lines to an interactive shell?