1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 09:27:59 +00:00

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.

[originally from svn r10023]
This commit is contained in:
Simon Tatham 2013-08-17 16:06:27 +00:00
parent a44366585f
commit d35a41f6ba
8 changed files with 44 additions and 126 deletions

View File

@ -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).

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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)) &&

View File

@ -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)
{
/*

View File

@ -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 */

View File

@ -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.