help-octave
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug in gnuplot_x11


From: John W. Eaton
Subject: bug in gnuplot_x11
Date: Thu, 26 Feb 1998 03:03:22 -0600

I'm using 3.6beta 340 with the X11 terminal type.  I've seen the
following problem on Intel systems running Linux and DEC Alpha systems
running Digital Unix, but it is probably not specific to those systems.

If I put the following commands in a file and execute them with the
load command, only the first line is plotted.

  plot sin (x)
  pause (1)
  clear
  replot cos (x)

If either the pause or clear command is removed, both lines are
plotted, but I don't think the problem is related to either of those
commands, or the replot command.  Instead, it appears that the gnuplot
X11 external driver program is not reading input correctly.  I think
the ultimate cause of the problem is that it expects to be able to
call select to find out if additional input is available to read, but
it also calls fgets, which may buffer input, causing select to think
that there is no more input available even when actually there is.

Here is a patch.  It fixes the problem by calling read and handling
the buffering directly instead of using fgets.

Thanks,

jwe


*** gplt_x11.c.orig     Tue Jul 22 18:20:37 1997
--- gplt_x11.c  Thu Feb 26 02:22:57 1998
***************
*** 239,244 ****
--- 239,245 ----
  
  #define Nbuf 1024
  char buf[Nbuf], **commands = (char **)0;
+ static int buffered_input_available = 0;
  
  FILE *X11_ipc;
  char X11_ipcpath[32];
***************
*** 318,335 ****
  void mainloop() {
     int nf, nfds, cn = ConnectionNumber(dpy), in;
     struct timeval timeout, *timer = (struct timeval *)0;
!    fd_set rset, tset;
     unsigned long all = 0xffffffff;
  
     X11_ipc = stdin;
     in = fileno (X11_ipc);
  
-    FD_ZERO(&rset);
-    FD_SET(cn, &rset);
- 
-    FD_SET(in, &rset);
-    nfds = (cn > in) ? cn + 1 : in + 1;
- 
  #ifdef ISC22
  /* Added by Robert Eckardt, address@hidden */
     timeout.tv_sec  = 0;               /* select() in ISC2.2 needs timeout */
--- 319,330 ----
  void mainloop() {
     int nf, nfds, cn = ConnectionNumber(dpy), in;
     struct timeval timeout, *timer = (struct timeval *)0;
!    fd_set tset;
     unsigned long all = 0xffffffff;
  
     X11_ipc = stdin;
     in = fileno (X11_ipc);
  
  #ifdef ISC22
  /* Added by Robert Eckardt, address@hidden */
     timeout.tv_sec  = 0;               /* select() in ISC2.2 needs timeout */
***************
*** 348,354 ****
  
                XFlush(dpy);
                
!               tset = rset;
  #if defined(__hpux) && defined(__STDC__)
                nf = select(nfds, (int *)&tset, (int *)0, (int *)0, timer);
  #else
--- 343,366 ----
  
                XFlush(dpy);
                
!               FD_ZERO(&tset);
!               FD_SET(cn, &tset);
! 
!               /* Don't wait for events if we know that input is
!                * already sitting in a buffer.  Also don't wait for
!                * input to become available.
!                */
!               if (buffered_input_available) {
!                       timeout.tv_sec  = 0;
!                       timeout.tv_usec = 0;
!                       timer = &timeout;
!               } else {
!                       timer = (struct timeval *) 0;
!                       FD_SET(in, &tset);
!               }
! 
!               nfds = (cn > in) ? cn + 1 : in + 1;
! 
  #if defined(__hpux) && defined(__STDC__)
                nf = select(nfds, (int *)&tset, (int *)0, (int *)0, timer);
  #else
***************
*** 379,385 ****
                        process_event(&xe);
                        } while(XPending(dpy));
                }
!       if (FD_ISSET(in, &tset))
                        if (!record())
                                /* end of input */
                                return;
--- 391,398 ----
                        process_event(&xe);
                        } while(XPending(dpy));
                }
! 
!               if (FD_ISSET(in, &tset) || buffered_input_available)
                        if (!record())
                                /* end of input */
                                return;
***************
*** 618,623 ****
--- 631,689 ----
  }
  
  #ifndef VMS
+ 
+ /* Handle input.  Use read instead of fgets because stdio buffering
+  * causes trouble when combined with calls to select.
+  */
+ int read_input ()
+ {
+       static int rdbuf_size = 10*Nbuf;
+       static char rdbuf[10*Nbuf-1];
+       static int total_chars;
+       static int rdbuf_offset;
+       static int buf_offset;
+       static int partial_read = 0;
+       int fd = fileno (X11_ipc);
+ 
+       if (! partial_read)
+               buf_offset = 0;
+ 
+       if (! buffered_input_available) {
+               total_chars = read (fd, rdbuf, rdbuf_size);
+               buffered_input_available = 1;
+               partial_read = 0;
+               rdbuf_offset = 0;
+               if (total_chars < 0)
+                       return -1;
+       }
+ 
+       if (rdbuf_offset < total_chars) {
+               while (rdbuf_offset < total_chars && buf_offset < Nbuf) {
+                       char c = rdbuf[rdbuf_offset++];
+                       buf[buf_offset++] = c;
+                       if (c == '\n')
+                               break;
+               }
+ 
+               if (buf_offset == Nbuf) {
+                       fprintf(stderr, "\ngnuplot: buffer overflow in 
read_input!\n");
+                       fprintf(stderr, "gnuplot: X11 aborted.\n");
+                       EXIT(1);
+                       
+               } else
+                       buf[buf_offset] = '\0';
+       }
+ 
+       if (rdbuf_offset == total_chars) {
+               buffered_input_available = 0;
+               if (buf[buf_offset-1] != '\n')
+                       partial_read = 1;
+       }
+ 
+       return partial_read;
+ }
+ 
+ 
  
/*-----------------------------------------------------------------------------
   *   record - record new plot from gnuplot inboard X11 driver (Unix)
   
*---------------------------------------------------------------------------*/
***************
*** 625,631 ****
  int record()
  {
        static plot_struct *plot = plot_array;
!       while (fgets(buf, Nbuf, X11_ipc)) {
                switch (*buf)
                {
                        case 'G':                           /* enter graphics 
mode */
--- 693,705 ----
  int record()
  {
        static plot_struct *plot = plot_array;
! 
!       while (1) {
! 
!               int status = read_input (buf, Nbuf);
!               if (status != 0)
!                       return status;
! 
                switch (*buf)
                {
                        case 'G':                           /* enter graphics 
mode */
***************
*** 649,667 ****
                                continue;
                }
        }
- 
-       /* get here if fgets fails */
-       
- #ifdef OSK
-    if (feof(X11_ipc))      /* On OS-9 sometimes while resizing the window,  */
-       _cleareof (X11_ipc); /* and plotting data, the eof or error flag of   */
-    if (ferror(X11_ipc))    /* X11_ipc stream gets set, while there is       */
-         clearerr (X11_ipc);  /* nothing wrong! Probably a bug in my select()? 
*/
- #else
-    if (feof(X11_ipc) || ferror(X11_ipc)) return 0;
- #endif
- 
-       return 1;
  }
  
  #else    /* VMS */
--- 723,728 ----



reply via email to

[Prev in Thread] Current Thread [Next in Thread]