How to wait for a shell process to finish on ctrl+c before exiting?

mipri mipri at minimaltype.com
Sun Nov 24 16:05:14 UTC 2019


On Sunday, 24 November 2019 at 15:44:00 UTC, aliak wrote:
> I'm writing some command line tooling stuff, and one of the 
> command spins up a docker compose file (which in short, spins 
> up some services and aggregates the output of each service to 
> stdout).
>
> When a user presses ctrl+c, i would like to pass on the ctrl+c 
> to the spawned process and wait till it handles ctrl+c and then 
> let go of the current process.

This might be useful:
---
#! /usr/bin/env rdmd
import std;
import core.stdc.signal;

int spawnedPid;

extern(C) int kill(int pid, int sig) nothrow @nogc @system;
extern (C) int waitpid(int pid, int* status, int options) nothrow 
@nogc @system;

extern(C) void interruptHandler(int sig) nothrow @nogc @system {
     kill(spawnedPid, SIGTERM);
     waitpid(spawnedPid, null, 0);
}

int spawnProcessAndWait(string[] cmd) {
     auto pid = spawnProcess(cmd, stdin, stdout, stderr);
     spawnedPid = pid.processID;
     signal(SIGINT, &interruptHandler);
     int result = wait(pid);
     return result;
}

void main() {
     spawnProcessAndWait(["perl", "-le", "$SIG{INT} = sub { print 
'Ignoring interrupt' }; $SIG{TERM} = sub { print 'Got'; sleep 2; 
print 'Term' }; print 'Go'; sleep 10"]);
}
---

I don't just using this code, but running this and seeing how
it behaves. For example, you might be surprised by the output
if you hit control-C as soon as you see the "Go":

---
Go
^CIgnoring interrupt
Got
Term
---
with a 2s delay after 'Got'.

Or this output if you remove the Perl $SIG{INT} assignment:

---
Go
^C
---
with you dropped right back to the shell.


It's also possible to cause this code to exit with an exception
from the wait(), because there's no process for it wait for.


More information about the Digitalmars-d-learn mailing list