Hi Stanislav,
Am 15.10.23 um 15:18 schrieb Stanislav Maslovski:
Hi,
First of all, many thanks to everyone involved in developing and
maintaining gfortran!
I have been trying to use gfortran's function signal() to add a SIGINT
signal handler to my program. Gfortran's documentation for this function
says that, when the signal handler is called, it is given an argument of
integer type. However, when I try to access this argument in the
signal handler, my program segfaults.
Here are two examples:
================= this code segfaults ===================
program test_signal
implicit none
integer, parameter :: SIGINT = 2, SIG_ERR = -1
logical :: sig_received = .false.
common /signal/ sig_received
external sig_handler
if (signal(SIGINT, sig_handler) /= SIG_ERR) then
print *, "Signal handler installed"
else
print *, "Error in signal()"
endif
do while (.true.)
print *, "Waiting for signal..."
do while (.not. sig_received)
continue
enddo
print *, "Signal received!"
sig_received = .false.
enddo
end program
subroutine sig_handler(s)
implicit none
integer, parameter :: SIGINT = 2
integer, intent(in) :: s
logical sig_received
common /signal/ sig_received
if (s == SIGINT) sig_received = .true.
end subroutine
=========================================================
$ gfortran test_signal.f90
$ ./a.out
Signal handler installed
Waiting for signal...
^C
Program received signal SIGSEGV: Segmentation fault - invalid memory
reference.
Backtrace for this error:
#0 0x7f9c312218c2 in ???
#1 0x7f9c31220a55 in ???
#2 0x7f9c3105afcf in ???
at ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
#3 0x562929f153bc in ???
#4 0x7f9c3105afcf in ???
at ./signal/../sysdeps/unix/sysv/linux/x86_64/libc_sigaction.c:0
#5 0x562929f152f4 in ???
#6 0x562929f153a8 in ???
#7 0x7f9c310461c9 in __libc_start_call_main
at ../sysdeps/nptl/libc_start_call_main.h:58
#8 0x7f9c31046284 in __libc_start_main_impl
at ../csu/libc-start.c:360
#9 0x562929f150c0 in ???
#10 0xffffffffffffffff in ???
zsh: segmentation fault ./a.out
============= this code does not segfault ===============
program test_signal
implicit none
integer, parameter :: SIGINT = 2, SIG_ERR = -1
logical :: sig_received = .false.
common /signal/ sig_received
external sig_handler
if (signal(SIGINT, sig_handler) /= SIG_ERR) then
print *, "Signal handler installed"
else
print *, "Error in signal()"
endif
do while (.true.)
print *, "Waiting for signal..."
do while (.not. sig_received)
continue
enddo
print *, "Signal received!"
sig_received = .false.
enddo
end program
subroutine sig_handler(s)
implicit none
integer, intent(in) :: s
logical sig_received
common /signal/ sig_received
sig_received = .true.
end subroutine
=========================================================
What am I doing wrong?
the man page for signal states that the interface of the signal handler is:
void (*sighandler_t)(int);
which means that the signal number is passed by value, not by reference.
If you replace
integer, intent(in) :: s
by
integer, value :: s
you'll get the intended behavior.
With best regards,