From 9d5903b163908339d5284390fef00965519cf4f7 Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sat, 17 Aug 2013 16:06:35 +0000 Subject: [PATCH] Revamp Windows pending_netevent using toplevel callbacks. This greatly simplifies the process of calling select_result() from the top level after receiving WM_NETEVENT. [originally from svn r10024] --- windows/window.c | 56 ++++++++++++++++++++-------------------------- windows/winstuff.h | 5 +++++ 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/windows/window.c b/windows/window.c index b5a18e5a..ca7260bb 100644 --- a/windows/window.c +++ b/windows/window.c @@ -104,10 +104,6 @@ static int offset_width, offset_height; static int was_zoomed = 0; static int prev_rows, prev_cols; -static int pending_netevent = 0; -static WPARAM pend_netevent_wParam = 0; -static LPARAM pend_netevent_lParam = 0; -static void enact_pending_netevent(void); static void flash_window(int mode); static void sys_cursor_update(void); static int get_fullscreen_rect(RECT * ss); @@ -140,6 +136,12 @@ static struct { enum { SYSMENU, CTXMENU }; static HMENU savedsess_menu; +struct wm_netevent_params { + /* Used to pass data to wm_netevent_callback */ + WPARAM wParam; + LPARAM lParam; +}; + Conf *conf; /* exported to windlg.c */ static void conf_cache_data(void); @@ -871,9 +873,6 @@ int WINAPI WinMain(HINSTANCE inst, HINSTANCE prev, LPSTR cmdline, int show) /* The messages seem unreliable; especially if we're being tricky */ term_set_focus(term, GetForegroundWindow() == hwnd); - - if (pending_netevent) - enact_pending_netevent(); } finished: @@ -1120,19 +1119,11 @@ void cmdline_error(char *fmt, ...) /* * Actually do the job requested by a WM_NETEVENT */ -static void enact_pending_netevent(void) +static void wm_netevent_callback(void *vctx) { - static int reentering = 0; - extern int select_result(WPARAM, LPARAM); - - if (reentering) - return; /* don't unpend the pending */ - - pending_netevent = FALSE; - - reentering = 1; - select_result(pend_netevent_wParam, pend_netevent_lParam); - reentering = 0; + struct wm_netevent_params *params = (struct wm_netevent_params *)vctx; + select_result(params->wParam, params->lParam); + sfree(vctx); } /* @@ -2688,19 +2679,20 @@ static LRESULT CALLBACK WndProc(HWND hwnd, UINT message, } return 0; case WM_NETEVENT: - /* Notice we can get multiple netevents, FD_READ, FD_WRITE etc - * but the only one that's likely to try to overload us is FD_READ. - * This means buffering just one is fine. - */ - if (pending_netevent) - enact_pending_netevent(); - - pending_netevent = TRUE; - pend_netevent_wParam = wParam; - pend_netevent_lParam = lParam; - if (WSAGETSELECTEVENT(lParam) != FD_READ) - enact_pending_netevent(); - + { + /* + * To protect against re-entrancy when Windows's recv() + * immediately triggers a new WSAAsyncSelect window + * message, we don't call select_result directly from this + * handler but instead wait until we're back out at the + * top level of the message loop. + */ + struct wm_netevent_params *params = + snew(struct wm_netevent_params); + params->wParam = wParam; + params->lParam = lParam; + queue_toplevel_callback(wm_netevent_callback, params); + } return 0; case WM_SETFOCUS: term_set_focus(term, TRUE); diff --git a/windows/winstuff.h b/windows/winstuff.h index 65711728..e21773a0 100644 --- a/windows/winstuff.h +++ b/windows/winstuff.h @@ -240,6 +240,11 @@ GLOBAL void *logctx; #define FILTER_DYNLIB_FILES ("Dynamic Library Files (*.dll)\0*.dll\0" \ "All Files (*.*)\0*\0\0\0") +/* + * Exports from winnet.c. + */ +extern int select_result(WPARAM, LPARAM); + /* * winnet.c dynamically loads WinSock 2 or WinSock 1 depending on * what it can get, which means any WinSock routines used outside -- 2.45.1