Bug 20788 - Loading libgfortran.so clobbers C redirection of stdin/stdout/stderr
Summary: Loading libgfortran.so clobbers C redirection of stdin/stdout/stderr
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: libfortran (show other bugs)
Version: 4.0.0
: P2 normal
Target Milestone: 4.0.1
Assignee: Not yet assigned to anyone
URL: http://gcc.gnu.org/ml/fortran/2005-05...
Keywords: patch
Depends on:
Blocks:
 
Reported: 2005-04-06 12:24 UTC by Brian Ripley
Modified: 2005-05-10 08:36 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2005-05-02 07:52:44


Attachments
Reproduction details, partial fix. (536 bytes, text/plain)
2005-04-06 12:27 UTC, Brian Ripley
Details
diff of strace (see comment #7) (868 bytes, text/plain)
2005-04-15 13:50 UTC, Francois-Xavier Coudert
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Brian Ripley 2005-04-06 12:24:49 UTC
When using a C main program that has in any way loaded libgfortran.so,
redirected C stdin is broken.  This is used by the R project
<http://www.r-project.org> to run scripts, and even occurs even if
the main (C) program has dlopen-ed a DSO with compiled Fortran code
linked against libgfortran.so.

There is separate bug that stops GFORTRAN_STDIN_UNIT being set to a 
negative value to avoid the initialization that causes the problem.
Comment 1 Brian Ripley 2005-04-06 12:27:16 UTC
Created attachment 8547 [details]
Reproduction details, partial fix.
Comment 2 Tobias Schlüter 2005-04-10 10:20:44 UTC
Patch here: http://gcc.gnu.org/ml/fortran/2005-04/msg00278.html
Comment 3 GCC Commits 2005-04-10 10:38:13 UTC
Subject: Bug 20788

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	fxcoudert@gcc.gnu.org	2005-04-10 10:38:00

Modified files:
	libgfortran    : ChangeLog 
	libgfortran/runtime: environ.c 

Log message:
	PR libfortran/20788
	* runtime/environ.c (init_unsigned_integer): Function for
	environment variables we want to be positive.
	(init_integer): Function to allow negative environment
	variables (e.g. for GFORTRAN_STDIN_UNIT).

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libgfortran/ChangeLog.diff?cvsroot=gcc&r1=1.190&r2=1.191
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libgfortran/runtime/environ.c.diff?cvsroot=gcc&r1=1.9&r2=1.10

Comment 4 Francois-Xavier Coudert 2005-04-10 10:38:32 UTC
For your problem, an easy solution is to use static linking, which seems to
avoid that issue (that is, you program works as expected without having to set
GFORTRAN_STDIN_UNIT).

Otherwise, I commited a patch to fix the issue with negative GFORTRAN_*_UNIT
being ignored (on mainline only).
Comment 5 Brian Ripley 2005-04-10 18:33:14 UTC
Subject: Re:  Loading libgfortran.so clobbers C
 redirection of stdin

Thank you for the suggestion, which had already been tried.  It does not 
always work as the static library is not compiled with -fPIC and so cannot 
be linked into DSOs to be dlopen-ed.  E.g. it fails on x86_64.

Being unable to correctly compile a GNU project (R is a GNU project) with 
silent errors seems to us to be a quite serious bug.  It make 
gcc4/gfortran unusable on a common platform (x86_64), and easy to break on 
many others. (R is an extensible system, and loading any extension 
compiled against a dyanmic libgfortran leads silently to incorrect 
results.)

On Sun, 10 Apr 2005, fxcoudert at gcc dot gnu dot org wrote:

>
> ------- Additional Comments From fxcoudert at gcc dot gnu dot org  2005-04-10 10:38 -------
> For your problem, an easy solution is to use static linking, which seems to
> avoid that issue (that is, you program works as expected without having to set
> GFORTRAN_STDIN_UNIT).
>
> Otherwise, I commited a patch to fix the issue with negative GFORTRAN_*_UNIT
> being ignored (on mainline only).
>
> -- 
>           What    |Removed                     |Added
> ----------------------------------------------------------------------------
>   Last reconfirmed|2005-04-10 10:20:45         |2005-04-10 10:38:34
>               date|                            |
>
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20788
>
> ------- You are receiving this mail because: -------
> You reported the bug, or are watching the reporter.
>
>

Comment 6 Andrew Pinski 2005-04-10 20:33:47 UTC
(In reply to comment #5)
> Subject: Re:  Loading libgfortran.so clobbers C  redirection of stdin
Also 4.0.0's release of gfortran is only a preview, a lot more bug will be fixed for 4.0.1.
Comment 7 Francois-Xavier Coudert 2005-04-15 13:48:34 UTC
First: using stdio in a mixed Fortran/C is a small nightmare. For short term
purposes, I strongly suggest you use the GFORTRAN_STDIN_UNIT=-1 trick. That does
exactly what you want (that is, suggest that Fortran runtime library should not
mess with standard input).

Now, an intersting thing for wandering bug-fixers is that you can mix c and
fortran standard input if you disable preconnection and manually open
/proc/self/fd/0 to unit 5:

$ cat test.c 
#include <stdio.h>

void foo_(void)
{
    char buf[1024];
    while(1) {
      if(fgets(buf, 1024, stdin) == NULL) break;
      printf("%s", buf);
   }
}
$ gcc -c test.c
$ cat test1.f 
      external foo
      character*70 c
      read (*,'(A)') c
      print *, c
      print *, 'calling the C routine'
      call foo
      print *, 'end of the program'
      end
$ cat test2.f
      external foo
      character*70 c
      open (5, file='/proc/self/fd/0')
      read (*,'(A)') c
      print *, c
      print *, 'calling the C routine'
      call foo
      print *, 'end of the program'
      end
$ gfortran test1.f test.o
$ ./a.out < test.c       
 #include <stdio.h>                                                    
 calling the C routine
 end of the program
$ gfortran test2.f test.o
$ GFORTRAN_STDIN_UNIT=-1 ./a.out < test.c
 #include <stdio.h>                                                    
 calling the C routine
#include <stdio.h>

void foo_(void)
{
    char buf[1024];
    while(1) {
      if(fgets(buf, 1024, stdin) == NULL) break;
      printf("%s", buf);
   }
}
 end of the program


So, the question is: what is the difference between preconnection and manually
openning the unit? I did strace the two processes and I attach the diff of these
traces here (about 50 lines, easy to read). I think the solution to this problem
is here.
Comment 8 Francois-Xavier Coudert 2005-04-15 13:50:26 UTC
Created attachment 8648 [details]
diff of strace (see comment #7)
Comment 9 Francois-Xavier Coudert 2005-05-02 07:52:43 UTC
The problem is that we're using mmap on the preconnected units, which confuses
subsequent C I/O on the file.

Patch here: http://gcc.gnu.org/ml/fortran/2005-05/msg00008.html

Will be committed in source tree as soon as it's reviewed.
Comment 10 GCC Commits 2005-05-10 08:32:13 UTC
Subject: Bug 20788

CVSROOT:	/cvs/gcc
Module name:	gcc
Branch: 	gcc-4_0-branch
Changes by:	fxcoudert@gcc.gnu.org	2005-05-10 08:31:50

Modified files:
	libgfortran    : ChangeLog 
	libgfortran/io : unix.c 

Log message:
	PR libfortran/20788
	* io/unix.c (fd_to_stream): Add an avoid_mmap argument indicating
	we don't we to mmap this stream. Use fd_open instead of mmap_open
	in that case.
	(open_external): Call fd_to_stream with avoid_mmap = 0.
	(input_stream): Call fd_to_stream with avoid_mmap = 1.
	(output_stream): Likewise.
	(error_stream): Likewise.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libgfortran/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.163.2.25&r2=1.163.2.26
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libgfortran/io/unix.c.diff?cvsroot=gcc&only_with_tag=gcc-4_0-branch&r1=1.21.10.1&r2=1.21.10.2

Comment 11 GCC Commits 2005-05-10 08:35:12 UTC
Subject: Bug 20788

CVSROOT:	/cvs/gcc
Module name:	gcc
Changes by:	fxcoudert@gcc.gnu.org	2005-05-10 08:34:58

Modified files:
	libgfortran    : ChangeLog 
	libgfortran/io : read.c 

Log message:
	PR libfortran/20788
	Missing entry from previous commit:
	* io/unix.c (fd_to_stream): Add an avoid_mmap argument indicating
	we don't we to mmap this stream. Use fd_open instead of mmap_open
	in that case.
	(open_external): Call fd_to_stream with avoid_mmap = 0.
	(input_stream): Call fd_to_stream with avoid_mmap = 1.
	(output_stream): Likewise.
	(error_stream): Likewise.
	
	Really committing:
	* io/read.c (read_f): Accept 'e', 'E', 'd' and 'D' as first
	non-blank characters of a real number.

Patches:
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libgfortran/ChangeLog.diff?cvsroot=gcc&r1=1.210&r2=1.211
http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/libgfortran/io/read.c.diff?cvsroot=gcc&r1=1.8&r2=1.9

Comment 12 Francois-Xavier Coudert 2005-05-10 08:36:13 UTC
This one is fixed. Thanks for the bug report!