This is the mail archive of the
fortran@gcc.gnu.org
mailing list for the GNU Fortran project.
Re: [patch fortran] PR 13919 - Runtime "internal error" in IO
- From: Bud Davis <bdavis9659 at comcast dot net>
- To: Steven Bosscher <stevenb at suse dot de>, gfortran <fortran at gcc dot gnu dot org>, gcc-patches at gcc dot gnu dot org
- Date: Fri, 05 Mar 2004 20:11:07 -0600
- Subject: Re: [patch fortran] PR 13919 - Runtime "internal error" in IO
- References: <1077325456.4974.34.camel@localhost.localdomain> <4036B0DD.5020202@comcast.net> <200403030826.09723.stevenb@suse.de>
On Wed, 2004-03-03 at 01:26, Steven Bosscher wrote:
> On Saturday 21 February 2004 02:14, bud davis wrote:
> > Let's try this again :)
> >
> > problem was a segfault with an empty input file, finish_list_read has to
> > have something to work with or the setjmp / longjmp has big problems.
>
> I may misunderstand the problem, but shouldn't at_eol in
> finish_list_read just be set in this case?
>
> Gr.
> Steven
>
Steven,
You didn't misunderstand the problem, I did.
First off, let's just ignore the previous patch. :)
I went to look at the problem again from the beginning and found that it
only happened when dynamically linked. A few hours of confusion later..
This is what happens:
a routine called from st_read() was doing the setjmp(eof_jmp).
st_read then returns.
< a lot of things happen...>
a routine called from st_done() calls longjmp(eof_jmp).
AFAIK, this is wrong, you must cannot longump to a spot in a subroutine
you have already returned from.
This only happens when you are reading more than is available. If you
have 5 items in the file, and read only 5, then the longjump happens in
a "child" function from st_read which is OK.
Why this works on some platforms, and when statically linked on
i686/linux I dunno...
The patch below moves eof_jmp to the io lib global structure, and makes
sure eof_jmp is always initialized to a valid return point in st_done.
Here is a testsuite file, read_eof.f90:
! pr 13919, segfault when file is empty
open(unit=8,file='/tmp/any_file')
read(8,*,end=1)i
1 continue
end
Works with this test as well as the code snippet included in the PR. no
additional regressions.
Tested i686 / linux
--bud
2004-03-05 Bud Davis <bdavis9659@comcast.net>
PR 13919
* io/io.h (global_t):
* io/list_read.c (next_char,list_formatted_read,ist_formatted_read):
Move eof_jmp to a global structure.
* io/transfer.c(finalize_transfer) : Set up eof_jump for callers.
Index: gcc/libgfortran/io/io.h
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/Attic/io.h,v
retrieving revision 1.1.2.4
diff -c -3 -p -r1.1.2.4 io.h
*** gcc/libgfortran/io/io.h 19 Sep 2003 19:11:12 -0000 1.1.2.4
--- gcc/libgfortran/io/io.h 6 Mar 2004 01:27:35 -0000
*************** Boston, MA 02111-1307, USA. */
*** 23,30 ****
/* IO library include. */
#include "libgfortran.h"
-
#define DEFAULT_TEMPDIR "/var/tmp"
/* Basic types used in data transfers. */
--- 23,30 ----
/* IO library include. */
+ #include <setjmp.h>
#include "libgfortran.h"
#define DEFAULT_TEMPDIR "/var/tmp"
/* Basic types used in data transfers. */
*************** typedef struct
*** 300,305 ****
--- 300,306 ----
unit_blank blank_status;
enum {SIGN_S, SIGN_SS, SIGN_SP} sign_status;
int scale_factor;
+ jmp_buf eof_jump;
}
global_t;
Index: gcc/libgfortran/io/list_read.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/Attic/list_read.c,v
retrieving revision 1.1.2.6
diff -c -3 -p -r1.1.2.6 list_read.c
*** gcc/libgfortran/io/list_read.c 1 Jan 2004 13:57:04 -0000 1.1.2.6
--- gcc/libgfortran/io/list_read.c 6 Mar 2004 01:27:35 -0000
*************** Boston, MA 02111-1307, USA. */
*** 20,26 ****
#include "config.h"
- #include <setjmp.h>
#include <string.h>
#include <ctype.h>
#include "libgfortran.h"
--- 20,25 ----
*************** static int comma_flag, namelist_mode;
*** 48,54 ****
static char last_char, *saved_string;
static bt saved_type;
- static jmp_buf eof_jump;
/* Storage area for values except for strings. Must be large enough
--- 47,52 ----
*************** next_char (void)
*** 145,151 ****
}
if (length == 0)
! longjmp (eof_jump, 1);
c = *p;
done:
--- 143,149 ----
}
if (length == 0)
! longjmp (g.eof_jump, 1);
c = *p;
done:
*************** list_formatted_read (bt type, void *p, i
*** 1227,1233 ****
namelist_mode = 0;
! if (setjmp (eof_jump))
{
generate_error (ERROR_END, NULL);
return;
--- 1225,1231 ----
namelist_mode = 0;
! if (setjmp (g.eof_jump))
{
generate_error (ERROR_END, NULL);
return;
*************** namelist_read (void)
*** 1413,1419 ****
namelist_mode = 1;
! if (setjmp (eof_jump))
{
generate_error (ERROR_END, NULL);
return;
--- 1411,1417 ----
namelist_mode = 1;
! if (setjmp (g.eof_jump))
{
generate_error (ERROR_END, NULL);
return;
Index: gcc/libgfortran/io/transfer.c
===================================================================
RCS file: /cvs/gcc/gcc/libgfortran/io/Attic/transfer.c,v
retrieving revision 1.1.2.7
diff -c -3 -p -r1.1.2.7 transfer.c
*** gcc/libgfortran/io/transfer.c 7 Feb 2004 15:33:29 -0000 1.1.2.7
--- gcc/libgfortran/io/transfer.c 6 Mar 2004 01:27:36 -0000
*************** Boston, MA 02111-1307, USA. */
*** 55,61 ****
*/
unit_t *current_unit;
-
static int sf_seen_eor = 0;
char scratch[SCRATCH_SIZE];
--- 55,60 ----
*************** next_record (int done)
*** 1294,1299 ****
--- 1293,1305 ----
static void
finalize_transfer (void)
{
+
+ if (setjmp (g.eof_jump))
+ {
+ generate_error (ERROR_END, NULL);
+ return;
+ }
+
if ((ionml != NULL) && (ioparm.namelist_name != NULL))
{
if (ioparm.namelist_read_mode)