Last active
December 23, 2024 19:38
-
-
Save pchalamet/98b2eddece97f1f4d5799afbd0e0da2a to your computer and use it in GitHub Desktop.
Attempt to start a child process in parent group so it's automatically killed if parent die
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
using System.Runtime.InteropServices; | |
namespace ProcessGroup; | |
// | |
// Attempt to start a child process and enroll it in the same process group as the parent. | |
// Goal is to be able to kill the child process if the parent process is killed. | |
// | |
public static class Process | |
{ | |
[DllImport("libc")] | |
private static extern int getpid(); | |
[DllImport("libc")] | |
private static extern int getsid(int pid); | |
[DllImport("libc")] | |
private static extern int setpgid(int pid, int pgid); | |
[DllImport("libc")] | |
private static extern int getpgid(int pid); | |
[DllImport("libc")] | |
private static extern int posix_spawn( | |
out int pid, | |
string path, | |
IntPtr fileActions, | |
ref IntPtr attrp, | |
string?[] argv, | |
string?[] envp); | |
// P/Invoke declaration for posix_spawnattr_init | |
[DllImport("libc")] | |
private static extern int posix_spawnattr_init(ref IntPtr attrp); | |
[DllImport("libc")] | |
private static extern int posix_spawnattr_destroy(ref IntPtr attrp); | |
[DllImport("libc")] | |
private static extern int posix_spawnattr_setpgroup(ref IntPtr attrp, int pgroup); | |
[DllImport("libc")] | |
private static extern IntPtr strerror(int errnum); | |
private static void CheckError(string fun, int error) | |
{ | |
if (error != 0) | |
{ | |
IntPtr messagePtr = strerror(error); | |
var errstring = Marshal.PtrToStringAnsi(messagePtr) ?? "Unknown error"; | |
throw new Exception($"{fun} failed with error {error} ({errstring})"); | |
} | |
} | |
public static int Start(string process, params string[] args) | |
{ | |
Console.WriteLine($"Current pid is {getpid()}"); | |
Console.WriteLine($"Current session is {getsid(0)}"); | |
Console.WriteLine($"Current progress group is {getpgid(0)}"); | |
int err; | |
IntPtr attrp = IntPtr.Zero; | |
try | |
{ | |
err = posix_spawnattr_init(ref attrp); | |
CheckError("posix_spawnattr_init", err); | |
err = posix_spawnattr_setpgroup(ref attrp, 0); | |
CheckError("posix_spawnattr_setpgroup", err); | |
// Define arguments for the child process | |
string path = process; | |
string?[] argv = [..args, null]; | |
string?[] envp = [null]; // Use parent's environment | |
// Spawn the child process | |
err = posix_spawn(out int childPid, path, IntPtr.Zero, ref attrp, argv, envp); | |
CheckError("posix_spawn", err); | |
Console.WriteLine($"Child process started with PID: {childPid}"); | |
return childPid; | |
} | |
catch { | |
posix_spawnattr_destroy(ref attrp); | |
throw; | |
} | |
// NOTE: also does not work (error 13: Permission denied) | |
// // Set the child process to the same process group as the parent | |
// err = setpgid(childProcess.Id, 0) | |
// if (err != 0) | |
// { | |
// Console.WriteLine($"Failed to set process group: {err}"); | |
// childProcess.Kill(); | |
// return null; | |
// } | |
// return childProcess; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment