I have a strange problem with sshd (from openssh-2.9p2) on Solaris 7. My shell
is bash. When I open an ssh session , and type a Control-C to bash's prompt,
the shell hangs. (But, if I for instance run "sleep 10" (during which
time the pty is in cooked mode) and press Control-C, the sleep command is
interrupted quite normally, and the bash prompt returns.)
Adding some debugging printfs tell me that the read(fdout,...) in
serverloop.c:process_input() returns zero when I type the Control-C?! Some
Solaris quirk in pty behaviour related to interrupts in raw mode? Following this
read returning 0, sshd thinks it got an EOF, closes its side of the pty, but the
shell still thinks everything is OK, but of course can't get any input.
So, my next try is to comment out the fdout_eof assignment. But then again,
exiting from the ssh session causes the sshd to loop (printing tvp!=NULL kid 1
milli 100), and if I then press Control-C to the ssh client (where I already
have exited the shell in the ssh session), sshd loops tighter, getting 0 all the
time from the read(fdout). Hmm, more hacking...
A horrible hack that seems to "fix" my problem is:
--- /tmp/openssh-2.9p2/serverloop.c Sat Apr 14 02:28:03 2001
+++ serverloop.c Mon Jul 9 13:02:27 2001
@@ -74,4 +74,5 @@
static int stdin_eof = 0; /* EOF message received from client. */
static int fdout_eof = 0; /* EOF encountered reading from fdout. */
+static int fdout_maybe_eof = 0;
static int fderr_eof = 0; /* EOF encountered readung from fderr. */
static int fdin_is_tty = 0; /* fdin points to a tty. */
@@ -107,6 +108,9 @@
wait_pid, child_pid);
if (WIFEXITED(child_wait_status) ||
- WIFSIGNALED(child_wait_status))
+ WIFSIGNALED(child_wait_status)) {
child_terminated = 1;
+ if (fdout_maybe_eof)
+ fdout_eof = 1;
+ }
}
signal(SIGCHLD, sigchld_handler);
@@ -338,10 +342,14 @@
/* Read and buffer any available stdout data from the program. */
- if (!fdout_eof && FD_ISSET(fdout, readset)) {
+ if (!fdout_eof && (child_terminated || FD_ISSET(fdout, readset))) {
len = read(fdout, buf, sizeof(buf));
if (len < 0 && (errno == EINTR || errno == EAGAIN)) {
/* do nothing */
} else if (len <= 0) {
- fdout_eof = 1;
+ verbose ("read from fdout returns zero?");
+ if (child_terminated)
+ fdout_eof = 1;
+ else
+ fdout_maybe_eof = 1;
} else {
buffer_append(&stdout_buffer, buf, len);
But no doubt it would be much better if somebody who understands how ptys work
in Solaris 7 could figure out the *right* way to fix this. I don't recommend
adding that hack to the code.
With the old Yl?nen ssh 1.2.26, the behaviour is a bit different: A Control-C to
bash's prompt kills the shell completely, with SIGHUP eventually. BTW, with
Solaris 2.5.1, I didn't notice any of these problems.
--tml