Last active
January 6, 2026 20:53
-
-
Save mscdex/c175bc9afb2b9aa1f249c50dde0ff1fa to your computer and use it in GitHub Desktop.
Check if the process identified by a passed pidfd is still alive with node.js
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 'use strict'; | |
| // The pidfd fd passed to this process | |
| const pidfd = 3; | |
| const { openSync, read } = require('fs'); | |
| const { join } = require('path'); | |
| const RE_PID = /(?:^|\n)Pid:[ \t]*([-0-9]+)/; | |
| const sleep = (t) => new Promise((resolve, reject) => setTimeout(resolve, t)); | |
| (async() => { | |
| const procfd = openSync(join('/proc/self/fdinfo', pidfd.toString())); | |
| const isProcessAlive = (() => { | |
| const buffer = Buffer.allocUnsafe(512); | |
| const options = { | |
| buffer, | |
| offset: 0, | |
| length: buffer.length, | |
| position: 0, | |
| }; | |
| const executor = (resolve, reject) => { | |
| read(procfd, options, (err, nb, buf) => { | |
| if (err) | |
| return reject(err); | |
| const m = RE_PID.exec(buf.latin1Slice(0, nb)); | |
| if (!m) | |
| return reject(new Error('Non-pidfd file descriptor')); | |
| resolve(m[1] !== '-1'); | |
| }); | |
| }; | |
| return () => new Promise(executor); | |
| })(); | |
| // ... | |
| for (;;) { | |
| if (await isProcessAlive()) { | |
| console.log('process alive'); | |
| } else { | |
| console.log('process dead'); | |
| break; | |
| } | |
| await sleep(1000); | |
| } | |
| })(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #define _GNU_SOURCE | |
| #include <spawn.h> | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <sys/syscall.h> | |
| #include <sys/types.h> | |
| #include <sys/wait.h> | |
| #include <unistd.h> | |
| static int pidfd_open(pid_t pid, unsigned int flags) { | |
| return syscall(SYS_pidfd_open, pid, flags); | |
| } | |
| int main(int argc, char *argv[]) { | |
| int pidfd; | |
| if (argc != 2) { | |
| fprintf(stderr, "Usage: %s <pid>\n", argv[0]); | |
| exit(EXIT_SUCCESS); | |
| } | |
| pidfd = pidfd_open(atoi(argv[1]), 0); | |
| if (pidfd == -1) { | |
| perror("pidfd_open"); | |
| exit(EXIT_FAILURE); | |
| } | |
| pid_t child_pid; | |
| char* child_argv[] = {"node", "node.js", NULL}; | |
| posix_spawn_file_actions_t file_actions; | |
| if (posix_spawn_file_actions_init(&file_actions) != 0) { | |
| perror("posix_spawn_file_actions_init"); | |
| exit(EXIT_FAILURE); | |
| } | |
| if (posix_spawn_file_actions_adddup2(&file_actions, pidfd, 3) != 0) { | |
| perror("posix_spawn_file_actions_adddup2"); | |
| exit(EXIT_FAILURE); | |
| } | |
| int status = posix_spawnp( | |
| &child_pid, "node", &file_actions, NULL, child_argv, environ | |
| ); | |
| if (status == 0) { | |
| printf("Child process spawned with PID: %i\n", child_pid); | |
| if (waitpid(child_pid, &status, 0) != -1) { | |
| printf("Child exited with status %i\n", WEXITSTATUS(status)); | |
| } else { | |
| perror("waitpid"); | |
| exit(EXIT_FAILURE); | |
| } | |
| } else { | |
| fprintf(stderr, "posix_spawn error: %s\n", strerror(status)); | |
| exit(EXIT_FAILURE); | |
| } | |
| exit(EXIT_SUCCESS); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| `gcc -O2 parent.c -o parent` | |
| <spawn a process to monitor> | |
| `./parent <monitored process pid>` | |
| <kill monitored process> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment