Skip to content

Commit ff5950d

Browse files
committed
signal handling example
1 parent e52b7df commit ff5950d

File tree

7 files changed

+166
-0
lines changed

7 files changed

+166
-0
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,5 @@ set(CMAKE_CXX_STANDARD 11)
3535
add_subdirectory(c)
3636

3737
add_subdirectory(cxx)
38+
39+
add_subdirectory(signal)

signal/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
add_library(c_sigint OBJECT c_interface.c)
2+
3+
add_library(c_ifc OBJECT c_interface.F90)
4+
5+
add_executable(waitForSIGINT $<TARGET_OBJECTS:c_sigint> $<TARGET_OBJECTS:c_ifc>)
6+
if(WIN32)
7+
target_sources(waitForSIGINT PRIVATE main_windows.f90)
8+
else()
9+
target_sources(waitForSIGINT PRIVATE main_unix.f90)
10+
endif()

signal/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fortran signal handling, based on https://fortran-lang.discourse.group/t/volatile-needed/1648

signal/c_interface.F90

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
module c_interface
2+
3+
use, intrinsic :: ISO_C_Binding, only: C_FUNPTR
4+
5+
implicit none (type, external)
6+
7+
interface
8+
9+
subroutine signalterm_C(handler) bind(C)
10+
import C_FUNPTR
11+
type(C_FUNPTR), intent(in), value :: handler
12+
end subroutine signalterm_C
13+
14+
#ifndef __WIN32__
15+
subroutine signalusr1_C(handler) bind(C)
16+
import C_FUNPTR
17+
type(C_FUNPTR), intent(in), value :: handler
18+
end subroutine signalusr1_C
19+
#endif
20+
21+
end interface
22+
23+
end module c_interface

signal/c_interface.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <signal.h>
2+
3+
void signalterm_c(void (*handler)(int)){
4+
signal(SIGTERM, handler);
5+
}
6+
7+
#ifndef __WIN32__
8+
void signalusr1_c(void (*handler)(int)){
9+
signal(SIGUSR1, handler);
10+
}
11+
#endif

signal/main_unix.f90

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
program wait_for_SIGTERM
2+
use, intrinsic :: ISO_C_binding
3+
4+
use c_interface
5+
6+
implicit none (type, external)
7+
8+
logical, volatile :: interface_SIGTERM, interface_SIGUSR1
9+
10+
call init
11+
12+
do while( .not. interface_SIGTERM)
13+
enddo
14+
15+
contains
16+
17+
subroutine init()
18+
19+
call signalterm_c(c_funloc(catchSIGTERM))
20+
call signalusr1_c(c_funloc(catchSIGUSR1))
21+
call interface_setSIGTERM(.false.)
22+
call interface_setSIGUSR1(.false.)
23+
24+
end subroutine init
25+
26+
subroutine catchSIGTERM(signal) bind(C)
27+
!! Set global variable interface_SIGTERM to .true.
28+
!! details This function can be registered to catch signals send to the executable.
29+
integer(C_INT), value :: signal
30+
31+
32+
print'(a,i0)', ' received signal ',signal
33+
call interface_setSIGTERM(.not. interface_SIGTERM)
34+
35+
end subroutine catchSIGTERM
36+
37+
38+
subroutine catchSIGUSR1(signal) bind(C)
39+
!! Set global variable interface_SIGUSR1 to .true.
40+
!! This function can be registered to catch signals send to the executable.
41+
integer(C_INT), value :: signal
42+
43+
print'(a,i0)', ' received signal ',signal
44+
call interface_setSIGUSR1(.not. interface_SIGUSR1)
45+
46+
end subroutine catchSIGUSR1
47+
48+
49+
subroutine interface_setSIGTERM(state)
50+
!! Set global variable interface_SIGTERM.
51+
logical, intent(in) :: state
52+
53+
54+
interface_SIGTERM = state
55+
print*, 'set SIGTERM to',state
56+
57+
end subroutine interface_setSIGTERM
58+
59+
60+
subroutine interface_setSIGUSR1(state)
61+
!! Set global variable interface_SIGUSR.
62+
logical, intent(in) :: state
63+
64+
65+
interface_SIGUSR1 = state
66+
print*, 'set SIGUSR1 to',state
67+
68+
end subroutine interface_setSIGUSR1
69+
70+
end program

signal/main_windows.f90

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
program wait_for_SIGTERM
2+
use, intrinsic :: ISO_C_binding
3+
4+
use c_interface
5+
6+
implicit none (type, external)
7+
8+
logical, volatile :: interface_SIGTERM
9+
10+
call init
11+
12+
do while( .not. interface_SIGTERM)
13+
14+
15+
enddo
16+
17+
contains
18+
19+
subroutine init()
20+
21+
call signalterm_c(c_funloc(catchSIGTERM))
22+
call interface_setSIGTERM(.false.)
23+
24+
end subroutine init
25+
26+
subroutine catchSIGTERM(signal) bind(C)
27+
!! Set global variable interface_SIGTERM to .true.
28+
!! details This function can be registered to catch signals send to the executable.
29+
integer(C_INT), value :: signal
30+
31+
32+
print'(a,i0)', ' received signal ',signal
33+
call interface_setSIGTERM(.not. interface_SIGTERM)
34+
35+
end subroutine catchSIGTERM
36+
37+
38+
subroutine interface_setSIGTERM(state)
39+
!! Set global variable interface_SIGTERM.
40+
logical, intent(in) :: state
41+
42+
43+
interface_SIGTERM = state
44+
print*, 'set SIGTERM to',state
45+
46+
end subroutine interface_setSIGTERM
47+
48+
49+
end program

0 commit comments

Comments
 (0)