Regressions with [patch, libgfortran] PR35132, PR34954, and PR34974
Hans-Peter Nilsson
hp@bitrange.com
Thu Feb 21 09:05:00 GMT 2008
On Thu, 21 Feb 2008, Hans-Peter Nilsson wrote:
> On Tue, 19 Feb 2008, Jerry DeLisle wrote:
> > 2008-02-19 Jerry DeLisle <jvdelisle@gcc.gnu.org>
> >
> > PR libfortran/35132
> > * io/transfer.c (next_record_w): Truncate after the last record for
> > STREAM I/O.
Looks like it's this one.
A (processed) simulator trace has this diff for streamio_11.f90
at -O2 (">" means call-to, "<" means return-to):
--- pre/s11.ex Thu Feb 21 09:00:19 2008
+++ post/s11.ex Thu Feb 21 08:58:59 2008
@@ -756,6 +756,14 @@
> memcpy
< fd_write
< _gfortrani_next_record
+> fd_truncate
+> lseek
+> _lseek_r
+> _lseek
+< _lseek_r
+< lseek
+< fd_truncate
+< _gfortrani_next_record
< finalize_transfer
< _gfortran_st_write_done
> _gfortrani_free_format_data
@@ -858,6 +866,8 @@
< list_formatted_read_scalar
> read_character
> next_char
+> fd_alloc_r_at
+< next_char
< read_character
> push_char
> _gfortrani_get_mem
@@ -911,6 +921,96 @@
> fd_alloc_r_at
< next_char
< read_character
+> push_char
+< read_character
+> next_char
...
+> fd_alloc_r_at
+< next_char
+< read_character
> next_char
< read_character
> eat_separator
@@ -1101,324 +1201,12 @@
> memcmp
< _gfortrani_compare_string
< MAIN__
-> _gfortrani_compare_string
-> memcmp
-< _gfortrani_compare_string
...
+> _gfortran_abort
Meaning, it's the first condition in
if(str1 /= rec1 .or. str2 /= rec2) call abort()
that fails, and from the looks of it, fd_truncate doesn't do
anything useful here; it just lseeks to the desired position.
That's probably because of (at libgfortran configuration time):
checking for ftruncate... no
checking for chsize... no
(remember, cris-elf is one of those challenged newlib simulator
targets)
and libgfortran/io/unix.c:fd_truncate being:
static try
fd_truncate (unix_stream * s)
{
/* Non-seekable files, like terminals and fifo's fail the lseek so just
return success, there is nothing to truncate. If its not a pipe there
is a real problem. */
if (lseek (s->fd, s->logical_offset, SEEK_SET) == -1)
{
if (errno == ESPIPE)
return SUCCESS;
else
return FAILURE;
}
/* Using ftruncate on a seekable special file (like /dev/null)
is undefined, so we treat it as if the ftruncate succeeded. */
#ifdef HAVE_FTRUNCATE
if (s->special_file || ftruncate (s->fd, s->logical_offset))
#else
#ifdef HAVE_CHSIZE
if (s->special_file || chsize (s->fd, s->logical_offset))
#endif
#endif
{
s->physical_offset = s->file_length = 0;
return SUCCESS;
}
s->physical_offset = s->file_length = s->logical_offset;
s->active = 0;
return SUCCESS;
}
The comment lies; special_file is treated as if the ftruncate
call (or chsize) *fails*, not succeeds. And why set offset and
file_length to 0 instead of s->logical_offset? Why is that a
better "faked success" than actually faking it? (Maybe that's a
separate bug.) FWIW, I'd suggest using an #elif; helps
readability and patchability.
If it's not intended to actually work without neither
ftruncate nor chsize, how about enforcing that and fail at
configuration time instead?
Or should we try to cope, and there be a "if (0)" for the
!HAVE_FTRUNCATE && !HAVE_CHSIZE case (new #elif before the
endif, if it'd have been written like that), so the
"special_file || failed ftruncate call" case isn't executed for
such platforms? (I haven't tested that.)
brgds, H-P
More information about the Fortran
mailing list