This is the mail archive of the
mailing list for the Cygwin project.
Re: Ctrl-C and non-cygwin programs
(There's no need to CC me individually, I set the Reply-To: to the
Simon Marlow wrote:
> Ok, thanks. So the bit I didn't realise was that a process needs to be attached to an actual Windows console in order to get Ctrl-C events. This is a bit of a problem, because it essentially means that a Cygwin shell running in either CYGWIN=tty mode or in an xterm cannot behave like a Windows shell for invoking non-cygwin console programs. Any console program that relies on being able to catch Ctrl-C to clean up cannot be used reliably from an xterm.
This is hardly the only problem you will face when running non-Cygwin
programs attached to a pty. Native programs (that is, those that use
MSVCRT as C library) will see stdout as a pipe and thus will buffer
their output by default, which can be very confusing for interactive
programs when you get no output and then all of a sudden 4k worth. And
likewise for input, a native program will think that its stdin is a pipe
and not a console, and thus many interactive programs will fail to work
when attached to a pty, especially those with a password prompt. Try
using the Windows version of telnet.exe in a xterm, it ain't pretty. So
the ctrl-C behavior is just one in a long list.
> This is a shame, because I really like using Cygin xterm under windows - its terminal behaviour seems a lot more reliable than the Cygwin bash console.
The thing you need to realize is that the goal of the Cygwin project is
to provide the ability to compile and execute POSIX code without
modification. Replacing the Windows Console API with something else
that's usable for foreign/non-Cygwin apps is secondary.
To be able to accomplish this, the Cygwin DLL has to invent a number of
ficticious APIs and concepts that simply do not exist on Windows, or
exist in a limited matter but in such a restrictive way as to be
useless. The list of such fictions includes fork(), exec(), signals,
pseudoterminals, etc. The only way to maintain the illusion of these
things working is by having all processes "in on the joke", i.e. linked
against cygwin1.dll and cooperating. When you have a native application
in the mix that has no idea what a pty is, it's just going to see a
pipe. And a native application has no (real) concept of "how do I
handle SIGINT", all it has is this ConsoleCtrlHandler thing which only
works if it's attached to a console.
> Incedentally, what does bash do to the child process when it detects Ctrl-C and there's no console? TerminateProcess()?
No. Remember the whole idea is to run POSIX code unmodified? bash has
no idea that it's running under Windows, it's running the same code path
as it would on *nix. So on *nix, when you press ^C, the tty device
driver sends SIGINT to the foreground process group. The shell is not
involved in this at all, except that it is responsible for arranging all
of the processes in the pipeline into a process group. The difference
between Linux and Cygwin is that on Linux the tty device driver is part
of the kernel, but since this idea of a tty does not exist on Windows
this code is all in the cygwin DLL.
What you may be asking is, "in the case of a native program, since there
is nothing to receive a SIGINT, how does this turn into the process
being terminated (and the ConsoleCtrlHandler being run if it was
attached to a console)?" In the case of a Cygwin process exec()ing a
non-Cygwin process, the way this is handled is by leaving behind a stub
process. The stub is the remainder of the Cygwin process before it
exec()ed (recall that Windows has no actual exec(), so replacing one
process with another has to be faked by spawning a new process and then
pretending it has the PID of the exec()ed one), and its function is to
receive signals on behalf of the non-Cygwin process that it supposedly
exec()ed. When it receives a SIGINT and there is no console, the only
thing it can do is terminate the process.
Now, I suppose that it might be possible in this exec() emulation code
to always create a hidden, unused console for the non-Cygwin process
even if it will not actually be interacting with it, for the sole
purpose of being able to call this ConsoleCtrlHander stuff. I don't
know if this is possible or if it would break other things. It would be
extremely annoying to see a console flash and then disappear every time
a native program was executed from a pty. There may be a way to
suppress this flashing, but that would require even further kludging I'm
sure, and it may not be possible on older versions of Windows.
I think at the end of the day though the problem here is that getting
non-Cygwin applications to work sanely with ptys is not a high priority
compared to providing a full and rich set of emulation for POSIX APIs.
In other words, if you have problems using the Windows version of
telnet.exe you should install the inetutils package and use the Cygwin
version. And likewise, if you want your program to be able to
gracefully terminate with ^C under Cygwin, then make it a Cygwin app and
have it install an appropriate SIGINT handler. And even if there was a
way to solve the ^C problem, the input and output buffering problem
would still cause many native apps to fall down in strange ways when
connected to a tty. It's really more of a fundamental problem.
Also do note that there are Windows terminal programs that are built
around the Windows Console API that provide a better experience than the
default, but still within the confines of that API, i.e. not emulating
something entirely different as Cygwin does with ptys. There was a long
thread about this not too long ago, the main one mentioned was called
simply Console I believe:
> I have one suggestion: could this be documented somewhere please? I spent a lot of time searching mailing lists and documentation for the answer to this question, but didn't find it anywhere. Apologies if I missed it.
Well, the problem of ptys and native apps seems to come up again and
again so it is prime candidate for a FAQ if there isn't one already.
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html