From 43a1c4a467dcf78e1bf7f8aa71d2f685a79d757d Mon Sep 17 00:00:00 2001 From: simon Date: Thu, 8 Dec 2011 19:15:57 +0000 Subject: [PATCH] Arrange to call net_pending_errors on Unix, which we've never actually remembered to do before! Also some related fixes, such as that after we do so we should immediately stop selecting on the socket in question. git-svn-id: svn://svn.tartarus.org/sgt/putty@9363 cda61777-01e9-0310-a592-d414129be87e --- unix/gtkwin.c | 18 ++++++++++++++++++ unix/unix.h | 7 +++++++ unix/uxnet.c | 30 +++++++++++++++++++++--------- unix/uxplink.c | 4 ++++ unix/uxpterm.c | 10 ++++++++++ unix/uxsftp.c | 2 ++ 6 files changed, 62 insertions(+), 9 deletions(-) diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 334decb6..4b8a8dd8 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -2725,6 +2725,24 @@ void uxsel_input_remove(int id) { gdk_input_remove(id); } +int frontend_net_pending_error_idle_id; +int frontend_got_net_pending_errors = FALSE; +gboolean frontend_net_pending_errors(gpointer data) +{ + net_pending_errors(); + gtk_idle_remove(frontend_net_pending_error_idle_id); + frontend_got_net_pending_errors = FALSE; + return FALSE; +} +void frontend_net_error_pending(void) +{ + if (!frontend_got_net_pending_errors) { + frontend_got_net_pending_errors = TRUE; + frontend_net_pending_error_idle_id = + gtk_idle_add(frontend_net_pending_errors, NULL); + } +} + void setup_fonts_ucs(struct gui_data *inst) { int shadowbold = conf_get_int(inst->conf, CONF_shadowbold); diff --git a/unix/unix.h b/unix/unix.h index 37649d5b..2ffc3567 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -171,6 +171,13 @@ int init_ucs(struct unicode_data *ucsdata, char *line_codepage, void *sk_getxdmdata(void *sock, int *lenp); /* + * Function provided by front ends, and called by uxnet.c to indicate + * that net_pending_errors() would like to be called back when the + * front end has a spare moment and isn't deep in any other recursion. + */ +void frontend_net_error_pending(void); + +/* * General helpful Unix stuff: more helpful version of the FD_SET * macro, which also handles maxfd. */ diff --git a/unix/uxnet.c b/unix/uxnet.c index 45ea55df..e2302aa4 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -1048,6 +1048,16 @@ void try_send(Actual_Socket s) * plug_closing()) at some suitable future moment. */ s->pending_error = err; + /* + * Immediately cease selecting on this socket, so that + * we don't tight-loop repeatedly trying to do + * whatever it was that went wrong. + */ + uxsel_tell(s); + /* + * Notify the front end that it might want to call us. + */ + frontend_net_error_pending(); return; } } else { @@ -1414,15 +1424,17 @@ static void sk_tcp_set_frozen(Socket sock, int is_frozen) static void uxsel_tell(Actual_Socket s) { int rwx = 0; - if (s->listener) { - rwx |= 1; /* read == accept */ - } else { - if (!s->connected) - rwx |= 2; /* write == connect */ - if (s->connected && !s->frozen && !s->incomingeof) - rwx |= 1 | 4; /* read, except */ - if (bufchain_size(&s->output_data)) - rwx |= 2; /* write */ + if (!s->pending_error) { + if (s->listener) { + rwx |= 1; /* read == accept */ + } else { + if (!s->connected) + rwx |= 2; /* write == connect */ + if (s->connected && !s->frozen && !s->incomingeof) + rwx |= 1 | 4; /* read, except */ + if (bufchain_size(&s->output_data)) + rwx |= 2; /* write */ + } } uxsel_set(s->s, rwx, net_select_result); } diff --git a/unix/uxplink.c b/unix/uxplink.c index b3e5679d..85f5352a 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -585,6 +585,8 @@ static void version(void) exit(1); } +void frontend_net_error_pending(void) {} + int main(int argc, char **argv) { int sending; @@ -1107,6 +1109,8 @@ int main(int argc, char **argv) back->unthrottle(backhandle, try_output(TRUE)); } + net_pending_errors(); + if ((!connopen || !back->connected(backhandle)) && bufchain_size(&stdout_data) == 0 && bufchain_size(&stderr_data) == 0) diff --git a/unix/uxpterm.c b/unix/uxpterm.c index 370527a3..c18505bb 100644 --- a/unix/uxpterm.c +++ b/unix/uxpterm.c @@ -17,6 +17,16 @@ Backend *select_backend(Conf *conf) return &pty_backend; } +void net_pending_errors(void) +{ + /* + * Stub version of net_pending_errors(), because gtkwin.c has to + * be prepared to call it when linked into PuTTY and therefore we + * have to avoid a link failure when linking gtkwin.c in turn into + * a non-networked application. + */ +} + int cfgbox(Conf *conf) { /* diff --git a/unix/uxsftp.c b/unix/uxsftp.c index 61847d8e..c266fb72 100644 --- a/unix/uxsftp.c +++ b/unix/uxsftp.c @@ -605,6 +605,8 @@ char *ssh_sftp_get_cmdline(char *prompt, int no_fds_ok) } } +void frontend_net_error_pending(void) {} + /* * Main program: do platform-specific initialisation and then call * psftp_main(). -- 2.11.0