root/samples/pidfd/pidfd-metadata.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. do_child
  2. pidfd_clone
  3. sys_pidfd_send_signal
  4. pidfd_metadata_fd
  5. main

   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 }

/* [<][>][^][v][top][bottom][index][help] */