mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-10 09:58:01 +00:00
Try harder not to call connection_fatal twice.
If the server sends an SSH_MSG_DISCONNECT, then we call connection_fatal(). But if the server closes the network connection, then we call connection_fatal(). In situations where the former happens, the latter happens too. Currently, calling connection_fatal twice is especially bad on GTK because all dialogs are now non-modal and an assertion fails in the GTK front end when two fatal message boxes try to exist at the same time (the register_dialog system finds that slot is already occupied). But regardless of that, we'd rather not even _try_ to print two fatal boxes, because even if the front end doesn't fail an assertion, there's no guarantee that the _more useful_ one of the messages will end up being displayed. So a better fix is to have ssh.c make a sensible decision about which message is the helpful one - in this case, the actual error message out of the SSH_MSG_DISCONNECT, rather than the predictable fact of the connection having been slammed shut immediately afterwards - and only pass that one to the front end in the first place.
This commit is contained in:
parent
6dc6392596
commit
6cbca87a62
47
ssh.c
47
ssh.c
@ -930,6 +930,7 @@ struct ssh_tag {
|
|||||||
int exitcode;
|
int exitcode;
|
||||||
int close_expected;
|
int close_expected;
|
||||||
int clean_exit;
|
int clean_exit;
|
||||||
|
int disconnect_message_seen;
|
||||||
|
|
||||||
tree234 *rportfwds, *portfwds;
|
tree234 *rportfwds, *portfwds;
|
||||||
|
|
||||||
@ -1593,6 +1594,20 @@ static void ssh1_rdpkt(Ssh ssh)
|
|||||||
|
|
||||||
BinarySource_INIT(st->pktin, st->pktin->body, st->pktin->length);
|
BinarySource_INIT(st->pktin, st->pktin->body, st->pktin->length);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mild layer violation: if the message is a DISCONNECT, we
|
||||||
|
* should unset the close_expected flag, because now we _do_
|
||||||
|
* expect the server to close the network connection
|
||||||
|
* afterwards. That way, the more informative connection_fatal
|
||||||
|
* message for the disconnect itself won't fight with 'Server
|
||||||
|
* unexpectedly closed network connection'.
|
||||||
|
*/
|
||||||
|
if (st->pktin->type == SSH1_MSG_DISCONNECT) {
|
||||||
|
ssh->clean_exit = FALSE;
|
||||||
|
ssh->close_expected = TRUE;
|
||||||
|
ssh->disconnect_message_seen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
pq_push(&ssh->pq_full, st->pktin);
|
pq_push(&ssh->pq_full, st->pktin);
|
||||||
queue_idempotent_callback(&ssh->pq_full_consumer);
|
queue_idempotent_callback(&ssh->pq_full_consumer);
|
||||||
}
|
}
|
||||||
@ -2015,6 +2030,20 @@ static void ssh2_rdpkt(Ssh ssh)
|
|||||||
|
|
||||||
BinarySource_INIT(st->pktin, st->pktin->body, st->pktin->length);
|
BinarySource_INIT(st->pktin, st->pktin->body, st->pktin->length);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mild layer violation: if the message is a DISCONNECT, we
|
||||||
|
* should unset the close_expected flag, because now we _do_
|
||||||
|
* expect the server to close the network connection
|
||||||
|
* afterwards. That way, the more informative connection_fatal
|
||||||
|
* message for the disconnect itself won't fight with 'Server
|
||||||
|
* unexpectedly closed network connection'.
|
||||||
|
*/
|
||||||
|
if (st->pktin->type == SSH2_MSG_DISCONNECT) {
|
||||||
|
ssh->clean_exit = FALSE;
|
||||||
|
ssh->close_expected = TRUE;
|
||||||
|
ssh->disconnect_message_seen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
pq_push(&ssh->pq_full, st->pktin);
|
pq_push(&ssh->pq_full, st->pktin);
|
||||||
queue_idempotent_callback(&ssh->pq_full_consumer);
|
queue_idempotent_callback(&ssh->pq_full_consumer);
|
||||||
if (st->pktin->type == SSH2_MSG_NEWKEYS) {
|
if (st->pktin->type == SSH2_MSG_NEWKEYS) {
|
||||||
@ -2079,6 +2108,20 @@ static void ssh2_bare_connection_rdpkt(Ssh ssh)
|
|||||||
|
|
||||||
BinarySource_INIT(st->pktin, st->pktin->body, st->pktin->length);
|
BinarySource_INIT(st->pktin, st->pktin->body, st->pktin->length);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mild layer violation: if the message is a DISCONNECT, we
|
||||||
|
* should unset the close_expected flag, because now we _do_
|
||||||
|
* expect the server to close the network connection
|
||||||
|
* afterwards. That way, the more informative connection_fatal
|
||||||
|
* message for the disconnect itself won't fight with 'Server
|
||||||
|
* unexpectedly closed network connection'.
|
||||||
|
*/
|
||||||
|
if (st->pktin->type == SSH2_MSG_DISCONNECT) {
|
||||||
|
ssh->clean_exit = FALSE;
|
||||||
|
ssh->close_expected = TRUE;
|
||||||
|
ssh->disconnect_message_seen = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
pq_push(&ssh->pq_full, st->pktin);
|
pq_push(&ssh->pq_full, st->pktin);
|
||||||
queue_idempotent_callback(&ssh->pq_full_consumer);
|
queue_idempotent_callback(&ssh->pq_full_consumer);
|
||||||
}
|
}
|
||||||
@ -3379,7 +3422,8 @@ static void ssh_process_incoming_data(void *ctx)
|
|||||||
|
|
||||||
if (error_msg)
|
if (error_msg)
|
||||||
logevent(error_msg);
|
logevent(error_msg);
|
||||||
if (!ssh->close_expected || !ssh->clean_exit)
|
if ((!ssh->close_expected || !ssh->clean_exit) &&
|
||||||
|
!ssh->disconnect_message_seen)
|
||||||
connection_fatal(ssh->frontend, "%s", error_msg);
|
connection_fatal(ssh->frontend, "%s", error_msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -11959,6 +12003,7 @@ static const char *ssh_init(void *frontend_handle, void **backend_handle,
|
|||||||
ssh->exitcode = -1;
|
ssh->exitcode = -1;
|
||||||
ssh->close_expected = FALSE;
|
ssh->close_expected = FALSE;
|
||||||
ssh->clean_exit = FALSE;
|
ssh->clean_exit = FALSE;
|
||||||
|
ssh->disconnect_message_seen = FALSE;
|
||||||
ssh->state = SSH_STATE_PREPACKET;
|
ssh->state = SSH_STATE_PREPACKET;
|
||||||
ssh->size_needed = FALSE;
|
ssh->size_needed = FALSE;
|
||||||
ssh->eof_needed = FALSE;
|
ssh->eof_needed = FALSE;
|
||||||
|
Loading…
Reference in New Issue
Block a user