mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-04-20 04:28:07 -05:00
Defer error callback from localproxy_try_send.
If you call plug_closing directly from localproxy_try_send, which can in turn be called directly from sk_write, then the plug's implementation of plug_closing may well free things that the caller of sk_write expected not to have vanished. The corresponding routine in uxnet.c pushes that call to plug_closing into a toplevel callback, so let's do that here too.
This commit is contained in:
parent
e857e43361
commit
32a0de93bc
@ -27,6 +27,8 @@ typedef struct LocalProxySocket {
|
|||||||
bufchain pending_error_data;
|
bufchain pending_error_data;
|
||||||
enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
|
enum { EOF_NO, EOF_PENDING, EOF_SENT } outgoingeof;
|
||||||
|
|
||||||
|
int pending_error;
|
||||||
|
|
||||||
const Socket_vtable *sockvt;
|
const Socket_vtable *sockvt;
|
||||||
} LocalProxySocket;
|
} LocalProxySocket;
|
||||||
|
|
||||||
@ -132,9 +134,28 @@ static void sk_localproxy_close (Socket s)
|
|||||||
bufchain_clear(&ps->pending_output_data);
|
bufchain_clear(&ps->pending_output_data);
|
||||||
bufchain_clear(&ps->pending_error_data);
|
bufchain_clear(&ps->pending_error_data);
|
||||||
|
|
||||||
|
delete_callbacks_for_context(ps);
|
||||||
|
|
||||||
sfree(ps);
|
sfree(ps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void localproxy_error_callback(void *vs)
|
||||||
|
{
|
||||||
|
LocalProxySocket *ps = (LocalProxySocket *)vs;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Just in case other socket work has caused this socket to vanish
|
||||||
|
* or become somehow non-erroneous before this callback arrived...
|
||||||
|
*/
|
||||||
|
if (!ps->pending_error)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* An error has occurred on this socket. Pass it to the plug.
|
||||||
|
*/
|
||||||
|
plug_closing(ps->plug, strerror(ps->pending_error), ps->pending_error, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int localproxy_try_send(LocalProxySocket *ps)
|
static int localproxy_try_send(LocalProxySocket *ps)
|
||||||
{
|
{
|
||||||
int sent = 0;
|
int sent = 0;
|
||||||
@ -146,7 +167,10 @@ static int localproxy_try_send(LocalProxySocket *ps)
|
|||||||
bufchain_prefix(&ps->pending_output_data, &data, &len);
|
bufchain_prefix(&ps->pending_output_data, &data, &len);
|
||||||
ret = write(ps->to_cmd, data, len);
|
ret = write(ps->to_cmd, data, len);
|
||||||
if (ret < 0 && errno != EWOULDBLOCK) {
|
if (ret < 0 && errno != EWOULDBLOCK) {
|
||||||
plug_closing(ps->plug, strerror(errno), errno, 0);
|
if (!ps->pending_error) {
|
||||||
|
ps->pending_error = errno;
|
||||||
|
queue_toplevel_callback(localproxy_error_callback, ps);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
} else if (ret <= 0) {
|
} else if (ret <= 0) {
|
||||||
break;
|
break;
|
||||||
@ -291,6 +315,7 @@ Socket platform_new_connection(SockAddr addr, const char *hostname,
|
|||||||
ret->plug = plug;
|
ret->plug = plug;
|
||||||
ret->error = NULL;
|
ret->error = NULL;
|
||||||
ret->outgoingeof = EOF_NO;
|
ret->outgoingeof = EOF_NO;
|
||||||
|
ret->pending_error = 0;
|
||||||
|
|
||||||
bufchain_init(&ret->pending_input_data);
|
bufchain_init(&ret->pending_input_data);
|
||||||
bufchain_init(&ret->pending_output_data);
|
bufchain_init(&ret->pending_output_data);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user