From 463bd3d2fe8db546ef51eeb60b90d1e8c2a8af48 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 17 Aug 2013 16:06:27 +0000 Subject: [PATCH] Revamp net_pending_errors using toplevel callbacks. Again, I've removed the special-purpose ad-hockery from the assorted front end message loops that dealt with deferred handling of socket errors, and instead uxnet.c and winnet.c arrange that for themselves by calling the new general top-level callback mechanism. git-svn-id: http://svn.tartarus.org/sgt/putty@10023 cda61777-01e9-0310-a592-d414129be87e --- network.h | 6 ----- unix/gtkwin.c | 18 -------------- unix/unix.h | 7 ------ unix/uxnet.c | 62 ++++++++++++++++++------------------------------ unix/uxplink.c | 2 -- unix/uxpterm.c | 10 -------- windows/window.c | 6 ----- windows/winnet.c | 59 ++++++++++++++++----------------------------- 8 files changed, 44 insertions(+), 126 deletions(-) diff --git a/network.h b/network.h index b432ccae..f390a5d0 100644 --- a/network.h +++ b/network.h @@ -190,12 +190,6 @@ const char *sk_addr_error(SockAddr addr); */ #define sk_set_frozen(s, is_frozen) (((*s)->set_frozen) (s, is_frozen)) -/* - * Call this after an operation that might have tried to send on a - * socket, to clean up any pending network errors. - */ -void net_pending_errors(void); - /* * Simple wrapper on getservbyname(), needed by ssh.c. Returns the * port number, in host byte order (suitable for printf and so on). diff --git a/unix/gtkwin.c b/unix/gtkwin.c index 7bc41cc9..59a5c383 100644 --- a/unix/gtkwin.c +++ b/unix/gtkwin.c @@ -2843,24 +2843,6 @@ 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); - } -} - char *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 a9f00bf2..c2f9aeb1 100644 --- a/unix/unix.h +++ b/unix/unix.h @@ -173,13 +173,6 @@ 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 d8460c19..9fc649f7 100644 --- a/unix/uxnet.c +++ b/unix/uxnet.c @@ -1025,6 +1025,26 @@ void *sk_getxdmdata(void *sock, int *lenp) return buf; } +/* + * Deal with socket errors detected in try_send(). + */ +static void socket_error_callback(void *vs) +{ + Actual_Socket s = (Actual_Socket)vs; + + /* + * Just in case other socket work has caused this socket to vanish + * or become somehow non-erroneous before this callback arrived... + */ + if (!find234(sktree, s, NULL) || !s->pending_error) + return; + + /* + * An error has occurred on this socket. Pass it to the plug. + */ + plug_closing(s->plug, strerror(s->pending_error), s->pending_error, 0); +} + /* * The function which tries to send on a socket once it's deemed * writable. @@ -1073,9 +1093,10 @@ void try_send(Actual_Socket s) */ uxsel_tell(s); /* - * Notify the front end that it might want to call us. + * Arrange to be called back from the top level to + * deal with the error condition on this socket. */ - frontend_net_error_pending(); + queue_toplevel_callback(socket_error_callback, s); return; } } else { @@ -1352,43 +1373,6 @@ static int net_select_result(int fd, int event) return 1; } -/* - * Deal with socket errors detected in try_send(). - */ -void net_pending_errors(void) -{ - int i; - Actual_Socket s; - - /* - * This might be a fiddly business, because it's just possible - * that handling a pending error on one socket might cause - * others to be closed. (I can't think of any reason this might - * happen in current SSH implementation, but to maintain - * generality of this network layer I'll assume the worst.) - * - * So what we'll do is search the socket list for _one_ socket - * with a pending error, and then handle it, and then search - * the list again _from the beginning_. Repeat until we make a - * pass with no socket errors present. That way we are - * protected against the socket list changing under our feet. - */ - - do { - for (i = 0; (s = index234(sktree, i)) != NULL; i++) { - if (s->pending_error) { - /* - * An error has occurred on this socket. Pass it to the - * plug. - */ - plug_closing(s->plug, strerror(s->pending_error), - s->pending_error, 0); - break; - } - } - } while (s); -} - /* * Each socket abstraction contains a `void *' private field in * which the client can keep state. diff --git a/unix/uxplink.c b/unix/uxplink.c index 36f3e2fc..85f91224 100644 --- a/unix/uxplink.c +++ b/unix/uxplink.c @@ -1116,8 +1116,6 @@ int main(int argc, char **argv) back->unthrottle(backhandle, try_output(TRUE)); } - net_pending_errors(); - run_toplevel_callbacks(); if ((!connopen || !back->connected(backhandle)) && diff --git a/unix/uxpterm.c b/unix/uxpterm.c index 6542fbba..1f4f20c2 100644 --- a/unix/uxpterm.c +++ b/unix/uxpterm.c @@ -17,16 +17,6 @@ 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/windows/window.c b/windows/window.c index 77e4e9eb..b5a18e5a 100644 --- a/windows/window.c +++ b/windows/window.c @@ -874,8 +874,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) if (pending_netevent) enact_pending_netevent(); - - net_pending_errors(); } finished: @@ -2349,7 +2347,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, InvalidateRect(hwnd, NULL, TRUE); reset_window(init_lvl); - net_pending_errors(); conf_free(prev_conf); } @@ -2412,7 +2409,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, break; if (back) back->special(backhandle, specials[i].code); - net_pending_errors(); } } break; @@ -2705,7 +2701,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, if (WSAGETSELECTEVENT(lParam) != FD_READ) enact_pending_netevent(); - net_pending_errors(); return 0; case WM_SETFOCUS: term_set_focus(term, TRUE); @@ -3087,7 +3082,6 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } } } - net_pending_errors(); return 0; case WM_INPUTLANGCHANGE: /* wParam == Font number */ diff --git a/windows/winnet.c b/windows/winnet.c index 4fddd72c..00a8290d 100644 --- a/windows/winnet.c +++ b/windows/winnet.c @@ -1345,6 +1345,26 @@ static void sk_tcp_close(Socket sock) sfree(s); } +/* + * Deal with socket errors detected in try_send(). + */ +static void socket_error_callback(void *vs) +{ + Actual_Socket s = (Actual_Socket)vs; + + /* + * Just in case other socket work has caused this socket to vanish + * or become somehow non-erroneous before this callback arrived... + */ + if (!find234(sktree, s, NULL) || !s->pending_error) + return; + + /* + * An error has occurred on this socket. Pass it to the plug. + */ + plug_closing(s->plug, strerror(s->pending_error), s->pending_error, 0); +} + /* * The function which tries to send on a socket once it's deemed * writable. @@ -1394,6 +1414,7 @@ void try_send(Actual_Socket s) * plug_closing()) at some suitable future moment. */ s->pending_error = err; + queue_toplevel_callback(socket_error_callback, s); return; } else { /* We're inside the Windows frontend here, so we know @@ -1666,44 +1687,6 @@ int select_result(WPARAM wParam, LPARAM lParam) return 1; } -/* - * Deal with socket errors detected in try_send(). - */ -void net_pending_errors(void) -{ - int i; - Actual_Socket s; - - /* - * This might be a fiddly business, because it's just possible - * that handling a pending error on one socket might cause - * others to be closed. (I can't think of any reason this might - * happen in current SSH implementation, but to maintain - * generality of this network layer I'll assume the worst.) - * - * So what we'll do is search the socket list for _one_ socket - * with a pending error, and then handle it, and then search - * the list again _from the beginning_. Repeat until we make a - * pass with no socket errors present. That way we are - * protected against the socket list changing under our feet. - */ - - do { - for (i = 0; (s = index234(sktree, i)) != NULL; i++) { - if (s->pending_error) { - /* - * An error has occurred on this socket. Pass it to the - * plug. - */ - plug_closing(s->plug, - winsock_error_string(s->pending_error), - s->pending_error, 0); - break; - } - } - } while (s); -} - /* * Each socket abstraction contains a `void *' private field in * which the client can keep state. -- 2.45.2