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] |
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
;;-----------------------------------------------------------------------------