SourceForge has been redesigned. Learn more.
Close

#1203 mouse zooming corrupts commands when using pipe input

closed-fixed
nobody
None
5
2015-03-23
2013-01-28
dkondor
No

Hi,

I encountered a strange problem when trying to use gnuplot from another program (piping commands into it with popen() and fprintf()). If I zoom using the mouse, the last issued 'plot' command gets garbled, as if a 'set' string was overlayed on it (see output below). This happens on Linux (Debian wheezy and Ubuntu 12.04, both 64-bit editions) with gnuplot versions 4.6 and 4.7 (in the case of 4.6, both the version in the Debian repository and the one I compile from source), with both the 'wxt' and 'x11' terminals. Version 4.4 (the one in the Ubuntu 12.04 repository) seems to work fine. Invoking gnuplot normally (i.e. 'interactive mode') also works fine. Steps to reproduce (I have attached the 'h2dt1k' datafile; other data produces similar results):

1. Start gnuplot with its input coming through a pipe (e.g. on Linux, use something like 'cat | gnuplot')
2. plot something on an interactive terminal ('wxt' or 'x11'
3. zoom in on the resulting plot using the mouse
4. gnuplot displays an error, complaining about that it cannot parse the commands given to it; it displays the last command overlayed on some commands which look like the commands that could be used to set the axis ranges (my guess is that a null-terminator is missing after the plot command)

dani@dani-desktop ~/t/p/pcapi> cat | gnuplot
p "h2dt1k"
#here I zoom in on some parts of the plot; the next line is the output of gnuplot:
gnuplot> p "h2dt1k"09327068002:0.737015692881]; set yr[0.561381452448:0.996228368585]; set x2r[ 0.381947: 0.670237]; set y2r[ 0.507635: 0.840450]
^
line 0: warning: integer overflow; changing to floating point

Regards,

Daniel

Discussion

  • dkondor

    dkondor - 2013-01-28

    sample datafile which produces the error (I don't think that the actual data is important; the issue might depend on the length of the filename given)

     
  • dkondor

    dkondor - 2013-01-28

    workaround for src/command.c

     
  • dkondor

    dkondor - 2013-01-28

    Hi,

    I think I have been able to identify the problematic points. The error occurs in 'src/command.c', at line 2136; in the case when the last command was read from a pipe, and also the replot was requested by a mouse zoom, the string 'gp_input_line' will be empty (i.e. gp_input_line[0] == 0), but the value 'c_token', and the expression 'token[c_token].start_index' will be nonzero, pointing to some previously used string in the 'gp_input_line' buffer, which will get copied to the command string just after the contents of 'replot_line', giving nonsense as result. I have created a very simple workaround (attached as a diff), which performs a sanity check: if the length of 'gp_input_line' is less than (or equal to) 'token[c_token].start_index', it does not bother to copy the additional parameters, and only uses the contents of 'replot_line' as input. This fixes my problem, however it might introduce other problems with handling replots (I checked only some very simple test cases, which seem to work fine); I think a real fix could ensure that 'token[c_token].start_index == 0' in this case, but since I'm not familiar with the code, I didn't want to modify any global variables, whose function I don't understand completely.

    Regards,

    Daniel

    p.s.: my diff is against the stable version (4.6.1)

     
  • dkondor

    dkondor - 2013-01-29

    Hi,

    I tried to find the real cause of this bug, and I have found the following (line numbers refer to the 4.6.1 release):
    In the case of reading input from a pipe, the function 'fgets_ipc()' gets called, which sets gp_input_line[0] to '\0' without touching the 'token' structures (command.c:2836). When I initiate a mouse zoom, the function 'do_string_and_free() gets called (command.c:451) which finds the token structures and the gp_input_line in this state (note that now gp_input_line[token[c_token].start_index] == '\0'] as it still points to the end of the last command). It "saves" these with an 'lf_push()', overwrites 'gp_input_line', executes the 'set xr ...' commands, and then "restores" the 'gp_input_line', 'token' and 'c_token' variables with "lf_pop()". While 'token' and 'c_token' get restored, the problem is with 'gp_input_line'. As the 'lf_push()' and 'lf_pop()' functions use 'strcpy()', only the first null-terminator (gp_input_line[0] == '\0' as it was set by 'fgets_ipc()') gets saved and restored. This results in that after the 'lf_pop()', we have: gp_input_line[0] == '\0' and the rest is the 'set xr ...' string, and now 'gp_input_line[token[c_token].start_index]' points to the middle of that. This causes trouble in the 'replotrequest()' function later. I think that a proper fix would adjust the behavior in 'fgets_ipc()'; is it necessary to set 'gp_input_line[0]' to '\0' first? If so, then is it possible to also clear 'token' and 'c_token'?

    Regards,

    Daniel

     
  • Ethan Merritt

    Ethan Merritt - 2013-01-30

    Thank you for the bug report and for your detailed analysis.

    It makes sense that the underlying problem would be in fgets_ipc(). To be internally consistent, the token structures should logically be reset at the same time the input line is truncated to zero length. The problem with this theory is that it worked in 4.4, but fgets_ipc() did not change between versions 4.4 and 4.6.

    One thing that did change is the handling of the new/old input line in lf_push(), so I am guessing that is where the error was introduced. Of course, it may still be that the correct fix should go somewhere else. For example, setting
    num_tokens = c_token = 0 in fgets_ipc() at the point where the input line is zeroed appears to fix your test case. But that would be a change, not a return to an earlier version of the code. So I don't know at this point what is the correct fix.

    I won't have time to look at this before next weekend. If you figure it out definitively before then, great. Otherwise I'll see what I can figure out..

     
  • Ethan Merritt

    Ethan Merritt - 2013-02-02

    My tentative fix is attached as a patch below. It sets c_token = num_tokens = 0 just before calling read_line(). That's basically the same fix as you propose except that it is applied as early in the sequence of events as possible.

     
  • dkondor

    dkondor - 2013-02-03

    Hi,

    thanks for the quick reply. I tested your patch, it does fix the behavior in the case of piped input, but it also breaks the non-piped (interactive) input. I get the following error on the second mouse zoom attempt:

    Terminal type set to 'wxt'
    gnuplot> p sin(x)
    gnuplot> undefined variable: p

    gnuplot>

    I think the problem is that the 'rlgets()' and the 'fgets_ipc()' functions behave differently. While the latter sets dest[0] = '\0' (which caused the original problem when using piped input), the 'rlgets()' function does not do this; the provided buffer is not touched until a line has been read. So now, I have (e.g. in the case when the 'replotrequest()' function is called because of a mouse zoom):

    1. piped input:
    (gdb) print gp_input_line + token[c_token].start_index
    $1 = 0xa56850 ""
    (gdb) print token[c_token].start_index
    $2 = 0
    works fine

    2. interactive input:
    (gdb) print gp_input_line + token[c_token].start_index
    $1 = 0xee7850 "plot sin(x)"
    (gdb) print token[c_token].start_index
    $2 = 0
    produces the error; actually this results in the contents of 'gp_input_line' getting duplicated:
    (gdb) break 2211
    Breakpoint 2 at 0x4222ef: file command.c, line 2211.
    (gdb) cont
    Continuing.

    Breakpoint 2, replotrequest () at command.c:2211
    2211 screen_ok = FALSE;
    (gdb) print gp_input_line
    $4 = 0xee7850 "plot sin(x)plot sin(x)"

    I now think that maybe setting 'gp_input_line[0] = '\0'' explicitly in the function 'read_line()' should fix this. Of course, there could be other side effects. I attach a modified version of your patch, witch does this; for me, it seems to work (on simple test plots).

     
  • dkondor

    dkondor - 2013-02-03

    clear token count + clear input line (command.c)

     
  • Ethan Merritt

    Ethan Merritt - 2013-02-28
    • labels: User Interface -->
    • status: open --> closed-fixed
    • milestone: --> 5.0
     

Log in to post a comment.