From: David Duffy on
I am a bit confused by the following example, which tries to call the
unix (linux) popen(), fgets(), pclose(). It works as I would expect
when compiled by g95, but the gfortran compiled code hangs around the first
fgets(),

#0 0xb7fcd424 in __kernel_vsyscall ()
#1 0xb7f091e3 in read () from /lib/i686/cmov/libc.so.6
#2 0xb7ea2fde in _IO_file_underflow () from /lib/i686/cmov/libc.so.6
#3 0xb7ea4d3b in _IO_default_uflow () from /lib/i686/cmov/libc.so.6
#4 0xb7ea62f2 in __uflow () from /lib/i686/cmov/libc.so.6
#5 0xb7e98c96 in _IO_getline_info () from /lib/i686/cmov/libc.so.6
#6 0xb7e98be1 in _IO_getline () from /lib/i686/cmov/libc.so.6
#7 0xb7e97aea in fgets () from /lib/i686/cmov/libc.so.6

and sunf95 gives
INTERNAL COMPILER ERROR around c_associated(fgets(lin,
clen, fp%handle).

Unfortunately g95 seems fairly forgiving when I do stupid things
interoperating with C.

!
! Fortran interface to popen
!
module fpipes
use, intrinsic :: ISO_C_BINDING
type, public :: streampointer
type (c_ptr) :: handle = c_null_ptr
end type streampointer
! popen
interface
function popen(path, mode) bind(C, name='popen')
use, intrinsic :: ISO_C_BINDING
character(kind=c_char), dimension(*) :: path, mode
type (c_ptr) :: popen
end function
end interface
! fgets
interface
function fgets(buf, siz, handle) bind(C, name='fgets')
use, intrinsic :: ISO_C_BINDING
type (c_ptr) :: fgets
character(kind=c_char), dimension(*) :: buf
integer(kind=c_int), value :: siz
type (c_ptr), value :: handle
end function
end interface
! pclose
interface
function pclose(handle) bind(C, name='pclose')
use, intrinsic :: ISO_C_BINDING
integer(c_int) :: pclose
type (c_ptr), value :: handle
end function
end interface
end module fpipes
!
! Main program
!
program test
use fpipes
integer, parameter :: BUFLEN=50000
character(len=BUFLEN) :: lin
character (len=3) :: mode
integer (kind=c_int) :: clen
integer :: eos, i
type(streampointer) :: fp

call get_command(lin)
if (lin == ' ' .or. lin == '-h' .or. lin == '--help') then
write(*,'(a)') 'Usage: run-process <command>'
stop
end if
clen=BUFLEN-1
mode='r'
fp%handle = popen(trim(lin) // C_NULL_CHAR, trim(mode) // C_NULL_CHAR)
if (.not.c_associated(fp%handle)) then
write(*,*) 'ERROR: Could not open pipe!'
stop
else
write(*,*) 'Opened pipe successfully'
end if
do while (c_associated(fgets(lin, clen, fp%handle)))
eos=2
do i=1, BUFLEN
if (lin(i:i) == C_NULL_CHAR) then
eos=i-2
exit
end if
end do
write(*,*) eos, ': "', trim(lin(1:eos)), '"'
end do
ios = pclose(fp%handle)
end program test


--
| David Duffy (MBBS PhD) ,-_|\
| email: davidD(a)qimr.edu.au ph: INT+61+7+3362-0217 fax: -0101 / *
| Epidemiology Unit, Queensland Institute of Medical Research \_,-._/
| 300 Herston Rd, Brisbane, Queensland 4029, Australia GPG 4D0B994A v
From: Tobias Burnus on
On 12/02/2009 08:38 AM, David Duffy wrote:
> I am a bit confused by the following example, which tries to call the
> unix (linux) popen(), fgets(), pclose(). It works as I would expect
> when compiled by g95, but the gfortran compiled code hangs around the first
> fgets()

Well, the reason why you are confused is because you looked at the wrong
spot.

> call get_command(lin)
> if (lin == ' ' .or. lin == '-h' .or. lin == '--help') then
[...]
> fp%handle = popen(trim(lin) // C_NULL_CHAR, [...]

You assume that g95 returns the same result as gfortran for
get_command(). If I call "./a.out echo" then g95's get_command returns
lin == "echo" while gfortran, NAG, ifort, and open95 return "./a.out echo".

Thus you are popening your program all the time when compiling with
gfortran ...

Tobias
From: Reinhold Bader on
Hello,

David Duffy schrieb:
> I am a bit confused by the following example, which tries to call the
> unix (linux) popen(), fgets(), pclose(). It works as I would expect
> when compiled by g95, but the gfortran compiled code hangs around the first
> fgets(),
>
> #0 0xb7fcd424 in __kernel_vsyscall ()
> #1 0xb7f091e3 in read () from /lib/i686/cmov/libc.so.6
> #2 0xb7ea2fde in _IO_file_underflow () from /lib/i686/cmov/libc.so.6
> #3 0xb7ea4d3b in _IO_default_uflow () from /lib/i686/cmov/libc.so.6
> #4 0xb7ea62f2 in __uflow () from /lib/i686/cmov/libc.so.6
> #5 0xb7e98c96 in _IO_getline_info () from /lib/i686/cmov/libc.so.6
> #6 0xb7e98be1 in _IO_getline () from /lib/i686/cmov/libc.so.6
> #7 0xb7e97aea in fgets () from /lib/i686/cmov/libc.so.6
>
> and sunf95 gives
> INTERNAL COMPILER ERROR around c_associated(fgets(lin,
> clen, fp%handle).

I can reproduce this for SS 12U1.

>
> Unfortunately g95 seems fairly forgiving when I do stupid things
> interoperating with C.

I think there is a difference in how different compilers execute the
subroutine get_command(). In particular, g95 appears to not include
the name of the executed command itself in the returned string; from
the description in the standard I consider this to be a bug in g95.

Replacing the call by

call get_command_argument(1,lin)

which I think is nearer to the semantics you want anyway,
things seem to be fine for ifort, nagfor, gfortran.

Regards
Reinhold
>

From: glen herrmannsfeldt on
David Duffy <davidD(a)orpheus.qimr.edu.au> wrote:
> I am a bit confused by the following example, which tries to call the
> unix (linux) popen(), fgets(), pclose(). It works as I would expect
> when compiled by g95, but the gfortran compiled code hangs around the first
> fgets(),

> #0 0xb7fcd424 in __kernel_vsyscall ()
> #1 0xb7f091e3 in read () from /lib/i686/cmov/libc.so.6
> #2 0xb7ea2fde in _IO_file_underflow () from /lib/i686/cmov/libc.so.6
> #3 0xb7ea4d3b in _IO_default_uflow () from /lib/i686/cmov/libc.so.6
> #4 0xb7ea62f2 in __uflow () from /lib/i686/cmov/libc.so.6
> #5 0xb7e98c96 in _IO_getline_info () from /lib/i686/cmov/libc.so.6
> #6 0xb7e98be1 in _IO_getline () from /lib/i686/cmov/libc.so.6
> #7 0xb7e97aea in fgets () from /lib/i686/cmov/libc.so.6

(snip of actual code)

It looks fine to me.

Some years ago (about 1990) I was working with HP/UX Fortran,
which has its own C interoperability. Among others, there is
a way to associate a unix file descriptor with a Fortran I/O
unit. I wrote a subroutine that would do popen, use a unix/C
macro to extract the file descriptor, and then open a Fortran
I/O unit. I could then do Fortran I/O (specifically O) to the
pipe. I was a little unsure what would happen on close, as
Fortran would likely fclose() the file instead of pclose(), but
it seemed to work. (The specific use was piping to lpr.)

About all I can think of is to write wrappers for the C functions,
and print out the arguments. Probably with %P for the pointers.

I wonder, though, if some important part of the C I/O library
is not being initialized.

-- glen
From: David Duffy on
Tobias Burnus <burnus(a)net-b.de> wrote:
> On 12/02/2009 08:38 AM, David Duffy wrote:
> You assume that g95 returns the same result as gfortran for
> get_command(). If I call "./a.out echo" then g95's get_command returns
> lin == "echo" while gfortran, NAG, ifort, and open95 return "./a.out echo".

> Thus you are popening your program all the time when compiling with
> gfortran ...

Indeed this was the problem, and explains the even wilder behaviour
when I used popen(commandline,"w") ;)

Cheers, David Duffy.

--
| David Duffy (MBBS PhD) ,-_|\
| email: davidD(a)qimr.edu.au ph: INT+61+7+3362-0217 fax: -0101 / *
| Epidemiology Unit, Queensland Institute of Medical Research \_,-._/
| 300 Herston Rd, Brisbane, Queensland 4029, Australia GPG 4D0B994A v