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