Toggle main menu visibility
Loading...
Searching...
No Matches
process_posix.f90
Go to the documentation of this file.
1
!> @file
2
!! @defgroup group_process_posix POSIX process utilities
3
!! Low-level POSIX implementation of process inspection routines.
4
!!
5
!! This module provides helper procedures used internally by
6
!! `fpx_process` to inspect running processes on Unix-like systems.
7
!!
8
!! Detection strategy:
9
!!
10
!! 1. `/proc/<pid>/comm` (Linux only, fastest)
11
!! 2. `ps`
12
!!
13
!! `/proc` is preferred because it requires no subprocess creation and
14
!! returns only the executable name.
15
!!
16
!! The `ps` fallback works on Linux, macOS, FreeBSD, OpenBSD,
17
!! Solaris and virtually every POSIX implementation.
18
!!
19
!! @ingroup group_process
20
module
fpx_process_posix
21
use,
intrinsic
:: iso_fortran_env
22
23
implicit none
;
private
24
25
public
:: get_process_name_posix, &
26
get_parent_pid_posix
27
28
contains
29
30
!> @brief Return parent PID (PPID) on POSIX systems
31
!!
32
!! Minimal, deterministic implementation based on /proc/self/status.
33
!! No shell, no parsing hacks, no external dependencies.
34
!! @ingroup group_process_posix
35
integer
function
get_parent_pid_posix
()
result
(ppid)
36
!private
37
integer
:: u, ios
38
character(256)
:: line
39
40
ppid = -1
41
42
open
(newunit=u, file=
'/proc/self/status'
, status=
'old'
, action=
'read'
, iostat=ios)
43
if
(ios /= 0)
return
44
do
45
read
(u,
'(A)'
, iostat=ios) line
46
if
(ios /= 0)
exit
47
48
! PPid line format:
49
! PPid:\t1234
50
if
(line(1:5) ==
'PPid:'
)
then
51
read
(line(6:), *) ppid
52
exit
53
end if
54
end do
55
56
close
(u)
57
end function
58
59
!> Return executable name of a process.
60
!!
61
!! Attempts Linux `/proc/<pid>/comm` first and falls back
62
!! to invoking `ps`.
63
!!
64
!! @param[in] pid process identifier
65
!!
66
!! @return executable name or empty string
67
!!
68
!! @ingroup group_process
69
function
get_process_name_posix(pid)
result
(name)
70
integer(int64)
,
intent(in)
:: pid
71
character(:)
,
allocatable
:: name
72
73
name = process_name_proc(pid)
74
75
if
(len(name) == 0)
then
76
name = process_name_ps(pid)
77
endif
78
end function
79
80
!> Linux implementation using `/proc/<pid>/comm`
81
!!
82
!! Returns an empty string if `/proc` is unavailable.
83
!!
84
!! @ingroup group_process
85
function
process_name_proc(pid)
result
(name)
86
integer(int64)
,
intent(in)
:: pid
87
character(:)
,
allocatable
:: name
88
!private
89
character(64)
:: filename
90
character(256)
:: line
91
integer
:: ios, unit
92
93
write
(filename,
'("/proc/",I0,"/comm")'
) pid
94
95
open
(newunit = unit, file = trim(filename), status =
'old'
, action =
'read'
, iostat = ios)
96
97
if
(ios /= 0)
then
98
name =
''
99
return
100
endif
101
102
read
(unit,
'(A)'
,iostat=ios) line
103
close
(unit)
104
105
if
(ios /= 0)
then
106
name =
''
107
else
108
name = trim(line)
109
endif
110
end function
111
112
!> Portable POSIX fallback using `ps`.
113
!!
114
!! Works on Linux, macOS, FreeBSD, OpenBSD and Solaris.
115
!!
116
!! @ingroup group_process
117
function
process_name_ps(pid)
result
(name)
118
integer(int64)
,
intent(in)
:: pid
119
character(:)
,
allocatable
:: name
120
!private
121
character(64)
:: command, tmpfile
122
character(256)
:: line
123
integer
:: ios, unit
124
125
tmpfile =
'__fpx_process.tmp'
126
127
write
(command,
'("ps -p ",I0," -o comm= > ",A)'
) pid, trim(tmpfile)
128
129
call
execute_command_line(command)
130
131
open
(newunit = unit, file = trim(tmpfile), status =
'old'
, action =
'read'
, iostat = ios)
132
if
(ios /= 0)
then
133
name =
''
134
close
(unit, status=
'delete'
)
135
return
136
endif
137
138
read
(unit,
'(A)'
, iostat=ios) line
139
if
(ios == 0)
then
140
name = trim(adjustl(line))
141
else
142
name =
''
143
endif
144
145
close
(unit, status=
'delete'
)
146
end function
147
148
end module
fpx_process_posix::get_parent_pid_posix
integer function, public get_parent_pid_posix()
Return parent PID (PPID) on POSIX systems.
Definition
process_posix.f90:36
© 2026 davidpfister. All Rights Reserved.