This is the mail archive of the guile@cygnus.com mailing list for the guile project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

close-pipe bug fix, and others


Included below are two bug fixes and one proposed change to
functionality (could be considered a bug fix by some)...

1) nasty bug in "close-pipe" in which closing the pipe can, in some
    circumstances, cause garbage collection to have the side effect of
    closing legitimately open ports.  To demonstrate the problem, create
    the following code as file "testpipe" and the load it into your scheme
    interpreter.

	(define a (open-input-pipe "ls"))
	(close-pipe a)
	(set! a (open-input-file "testpipe"))
	(write-line (read-line a))
	(write-line (read-line a))
	(gc)
	(write-line (read-line a))
	(write-line (read-line a))
	(close-port a)

    In guile 1.2 this code yields:

	(define a (open-input-pipe "ls"))
	(close-pipe a)
	#<eof>
	#<eof>

    Note that the act of performing garbage collection has caused the
    side effect of making the input file appear to have reached end of
    file.  By using the included patch to "posix.c" the code fragment
    has the correct behavior:

	(define a (open-input-pipe "ls"))
	(close-pipe a)
	(set! a (open-input-file "testpipe"))
	(write-line (read-line a))

    I wish I could say this bug was easy to find...  :-(

2) While trying to solve the first bug I noticed that when the
    scm_port_table is grown, it is allocating way too much memory (rather
    than allocating enough space for a *pointer* to a port table entry,
    it is allocating space for a whole port table entry).  See the patch
    to "ports.c" for the bug fix.

3) In order to help track down the first bug I added some code to the
    call to "fgetc" to check for error conditions and throw an exception
    upon read error.

    I would propose that all native file IO calls have error checking
    added and throw an appropriate exception.  Because "scm_fgetc" was
    not checking the error state on the stream, the bug in "close-pipe"
    was appearing as an apparent premature end of file (fgets return EOF
    on error and legitimate end of file) while loading scheme files.  By
    adding the error checking I was able to get specific error messages
    (in this case "bad file handle" because I was trying to read from an
    already closed stream).  My patch to "fports.c" includes only the
    change I made, but I would propose someone go in and fix the
    remaining calls.

Rob
-- 
------------------------------------------------------------------------
Rob Engle                                      grenoble@spimageworks.com
Sony Pictures Imageworks                             voice: 310-840-8203
9050 West Washington Boulevard                         fax: 310-840-8567
Culver City, CA  90232
------------------------------------------------------------------------


;;-----------------------------------------------------------------------------
(posix.c)
*** 1.2 1997/12/04 06:01:55
--- 1.3 1998/01/31 03:48:54
***************
*** 945,950 ****
--- 945,952 ----
              && SCM_OPENP (port), port, SCM_ARG1, s_close_pipe);
    SCM_DEFER_INTS;
    rv = pclose ((FILE *) SCM_STREAM (port));
+   scm_remove_from_port_table (port);
+   SCM_SETAND_CAR (port, ~SCM_OPN);
    if (rv == -1)
      scm_syserror (s_close_pipe);
    SCM_ALLOW_INTS;
;;-----------------------------------------------------------------------------
(ports.c)
*** 1.1 1997/12/04 06:01:53
--- 1.3 1998/02/01 22:17:42
***************
*** 243,249 ****
      {
        scm_port_table = ((struct scm_port_table **)
                        realloc ((char *) scm_port_table,
!                                (long) (sizeof (struct scm_port_table)
                                         * scm_port_table_room * 2)));
        /* !!! error checking */
        scm_port_table_room *= 2;
--- 243,249 ----
      {
        scm_port_table = ((struct scm_port_table **)
                        realloc ((char *) scm_port_table,
!                                (size_t)(sizeof(struct scm_port_table *)
                                         * scm_port_table_room * 2)));
        /* !!! error checking */
        scm_port_table_room *= 2;
;;-----------------------------------------------------------------------------
(fports.c)
*** 1.1 1997/12/04 06:01:32
--- 1.2 1998/01/31 03:49:31
***************
*** 280,289 ****
  scm_fgetc (s)
       FILE * s;
  {
!   if (feof (s))
      return EOF;
!   else
!     return fgetc (s);
  }
  
  #ifdef vms
--- 280,300 ----
  scm_fgetc (s)
       FILE * s;
  {
!   /* get the character */
!   int c = fgetc(s);
! 
!   /* if valid character, return it */
!   if (c != EOF)
!     return c;
! 
!   /* if natural end of file, return EOF */
!   if (feof(s))
      return EOF;
! 
!   /* handle file read error */
!   scm_syserror("fgetc");
! 
!   /*NOTREACHED*/
  }
  
  #ifdef vms
;;-----------------------------------------------------------------------------