Mail Archives: cygwin/2010/05/20/19:00:22
Hi. I'm a longtime cygwin user (since it was gnu-win32) who has struggled to
solve one particular long-standing disconnect between cygwin and native Win32
command-line utilities, notably that unless you're using a cygwin shell from a
cmd.exe window (or tools like Console2 that effectively co-opt the native
console), CTRL-C doesn't properly interrupt spawned native processes. For me
this has primarily been command-line builds and launches of Java applications
(mostly via ant). I'll press CTRL-C and the topmost process will terminate, but
I'll continue to see the various subprocesses cranking unless I kill them
explicitly.
I've seen numerous threads on this topic when Googling around for solutions and
I understand the developers' responses that they don't want to do anything that
deviates too far from the "it should just look like UNIX with no cygwin-specific
code changes", but the fact is that it's an annoyance.
It occurred to me today that perhaps there's a relatively simple workaround for
this problem that, while not 100% transparent, is pretty close once configured.
I wrote a simple shell script that acts as a wrapper for native Windows console
apps and registers a handler for SIGINT that, when caught, kills the process
tree of the spawned child process. I alias the commands that are subject to
these kinds of issues to be run through this wrapper and then it actually is
pretty seamless. Right now this wrapper relies on SysInternals (now Microsoft,
I think) pskill because of its ability to kill an entire Windows process tree,
but perhaps there's a cygwin command to do the same thing.
Here's the simple script (cmdwrapper.sh):
===============================================================
#!/bin/bash
PSKILL=C:/bin/pskill
# A simple signal handler that kills the child process if we've started one
killChildProcess() {
if [ -n "${CHILDPID}" ] ; then
# Use pskill to kill the entire family
# TODO: See if there's way to do this purely with cygwin
${PSKILL} -t ${CHILDPID}
fi
}
# Run the requested command line and remember the child PID
$* &
CHILDPID=$!
# Register the signal handler for CTRL-C/interrupt
trap 'killChildProcess' INT
# Wait for the child to finish normally and store the exit code
wait ${CHILDPID}
RESULT=$?
# Remove the signal handler (probably unnecessary since we're exiting anyway)
trap - INT
# Propagate the requested process' exit code to the caller
exit ${RESULT}
===============================================================
and here's how I've aliased, for example, ant to use it (by the way, I'd already
had to do create a function for ant to ensure that ant.bat is executed instead
of the shell script and to use Windows-style paths):
ant() {
PWD="`cygpath --windows \"${PWD}\"`" cmdwrapper.sh ant.bat $*
}
With these in place I can use mintty, rxvt, terminator, or any other pty-based
terminal with cygwin and run native Windows command-line utilities just as if I
were at a cmd.exe!
If anyone knows of a better way to do this, or if this problem is already
long-solved and I just missed the memo, please let me know. I don't care what
the solution happens to be; I just want a solution!
If this hasn't already been solved and other folks find this useful, great!
Please let me know if you think of any ways to improve this, especially if it's
removing the dependency on pskill and/or the need to explicitly alias commands
that should be executed this way. Also as a note to the cygwin developers,
perhaps something like this should become a standard cygwin utility similar to
cygpath? That would accomplish the goal of not contaminating cygwin itself but
facilitating this type of pairing.
Regards,
Scott
--
Problem reports: http://cygwin.com/problems.html
FAQ: http://cygwin.com/faq/
Documentation: http://cygwin.com/docs.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
- Raw text -