X-Spam-Check-By: sourceware.org Message-ID: <45742FA9.9B34794F@dessent.net> Date: Mon, 04 Dec 2006 06:24:41 -0800 From: Brian Dessent X-Mailer: Mozilla 4.79 [en] (Windows NT 5.0; U) MIME-Version: 1.0 To: "cygwin AT cygwin DOT com" Subject: Re: Ctrl-C and non-cygwin programs References: Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-IsSubscribed: yes Reply-To: cygwin AT cygwin DOT com Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com (There's no need to CC me individually, I set the Reply-To: to the list.) 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: or . > 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. Brian -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Problem reports: http://cygwin.com/problems.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/