Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/samples/pidfd/pidfd-metadata.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
3
#define _GNU_SOURCE
4
#include <err.h>
5
#include <errno.h>
6
#include <fcntl.h>
7
#include <inttypes.h>
8
#include <limits.h>
9
#include <sched.h>
10
#include <signal.h>
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#include <sys/stat.h>
15
#include <sys/syscall.h>
16
#include <sys/types.h>
17
#include <sys/wait.h>
18
#include <unistd.h>
19
20
#ifndef CLONE_PIDFD
21
#define CLONE_PIDFD 0x00001000
22
#endif
23
24
#ifndef __NR_pidfd_send_signal
25
#define __NR_pidfd_send_signal -1
26
#endif
27
28
static int do_child(void *args)
29
{
30
printf("%d\n", getpid());
31
_exit(EXIT_SUCCESS);
32
}
33
34
static pid_t pidfd_clone(int flags, int *pidfd)
35
{
36
size_t stack_size = 1024;
37
char *stack[1024] = { 0 };
38
39
#ifdef __ia64__
40
return __clone2(do_child, stack, stack_size, flags | SIGCHLD, NULL, pidfd);
41
#else
42
return clone(do_child, stack + stack_size, flags | SIGCHLD, NULL, pidfd);
43
#endif
44
}
45
46
static inline int sys_pidfd_send_signal(int pidfd, int sig, siginfo_t *info,
47
unsigned int flags)
48
{
49
return syscall(__NR_pidfd_send_signal, pidfd, sig, info, flags);
50
}
51
52
static int pidfd_metadata_fd(pid_t pid, int pidfd)
53
{
54
int procfd, ret;
55
char path[100];
56
57
snprintf(path, sizeof(path), "/proc/%d", pid);
58
procfd = open(path, O_DIRECTORY | O_RDONLY | O_CLOEXEC);
59
if (procfd < 0) {
60
warn("Failed to open %s\n", path);
61
return -1;
62
}
63
64
/*
65
* Verify that the pid has not been recycled and our /proc/<pid> handle
66
* is still valid.
67
*/
68
ret = sys_pidfd_send_signal(pidfd, 0, NULL, 0);
69
if (ret < 0) {
70
switch (errno) {
71
case EPERM:
72
/* Process exists, just not allowed to signal it. */
73
break;
74
default:
75
warn("Failed to signal process\n");
76
close(procfd);
77
procfd = -1;
78
}
79
}
80
81
return procfd;
82
}
83
84
int main(int argc, char *argv[])
85
{
86
int pidfd = -1, ret = EXIT_FAILURE;
87
char buf[4096] = { 0 };
88
pid_t pid;
89
int procfd, statusfd;
90
ssize_t bytes;
91
92
pid = pidfd_clone(CLONE_PIDFD, &pidfd);
93
if (pid < 0)
94
err(ret, "CLONE_PIDFD");
95
if (pidfd == -1) {
96
warnx("CLONE_PIDFD is not supported by the kernel");
97
goto out;
98
}
99
100
procfd = pidfd_metadata_fd(pid, pidfd);
101
close(pidfd);
102
if (procfd < 0)
103
goto out;
104
105
statusfd = openat(procfd, "status", O_RDONLY | O_CLOEXEC);
106
close(procfd);
107
if (statusfd < 0)
108
goto out;
109
110
bytes = read(statusfd, buf, sizeof(buf));
111
if (bytes > 0)
112
bytes = write(STDOUT_FILENO, buf, bytes);
113
close(statusfd);
114
ret = EXIT_SUCCESS;
115
116
out:
117
(void)wait(NULL);
118
119
exit(ret);
120
}
121
122