hw/xwin: Chain IOError handlers to avoid longjmp across threads

Avoid crashes on shutdown due to the undefined behaviour of calling longjmp() on the
result of setjmp() from a different thread, by chaining IOError handlers and only
jumping back up to the frame for this thread

Signed-off-by: Jon TURNEY <jon.turney@dronecode.org.uk>
Reviewed-by: Colin Harrison <colin.harrison@virgin.net>
This commit is contained in:
Jon TURNEY 2010-04-05 13:57:24 +01:00
parent 0659437f5e
commit 95b1391fe3
2 changed files with 52 additions and 25 deletions

View File

@ -63,6 +63,8 @@ extern Window g_iClipboardWindow;
static jmp_buf g_jmpEntry;
static int clipboardRestarts = 0;
static XIOErrorHandler g_winClipboardOldIOErrorHandler;
static pthread_t g_winClipboardProcThread;
Bool g_fUnicodeSupport = FALSE;
Bool g_fUseUnicode = FALSE;
@ -128,6 +130,11 @@ winClipboardProc (void *pvNotUsed)
ErrorF ("winClipboardProc - Warning: Locale not supported by X.\n");
}
/* Set error handler */
XSetErrorHandler (winClipboardErrorHandler);
g_winClipboardProcThread = pthread_self();
g_winClipboardOldIOErrorHandler = XSetIOErrorHandler (winClipboardIOErrorHandler);
/* Set jump point for Error exits */
iReturn = setjmp (g_jmpEntry);
@ -150,10 +157,6 @@ winClipboardProc (void *pvNotUsed)
/* Use our generated cookie for authentication */
winSetAuthorization();
/* Set error handler */
XSetErrorHandler (winClipboardErrorHandler);
XSetIOErrorHandler (winClipboardIOErrorHandler);
/* Initialize retry count */
iRetries = 0;
@ -511,8 +514,14 @@ winClipboardIOErrorHandler (Display *pDisplay)
{
ErrorF ("winClipboardIOErrorHandler!\n\n");
/* Restart at the main entry point */
longjmp (g_jmpEntry, WIN_JMP_ERROR_IO);
if (pthread_equal(pthread_self(),g_winClipboardProcThread))
{
/* Restart at the main entry point */
longjmp (g_jmpEntry, WIN_JMP_ERROR_IO);
}
if (g_winClipboardOldIOErrorHandler)
g_winClipboardOldIOErrorHandler(pDisplay);
return 0;
}

View File

@ -204,7 +204,11 @@ winUpdateWindowPosition (HWND hWnd, Bool reshape, HWND *zstyle);
*/
static jmp_buf g_jmpWMEntry;
static XIOErrorHandler g_winMultiWindowWMOldIOErrorHandler;
static pthread_t g_winMultiWindowWMThread;
static jmp_buf g_jmpXMsgProcEntry;
static XIOErrorHandler g_winMultiWindowXMsgProcOldIOErrorHandler;
static pthread_t g_winMultiWindowXMsgProcThread;
static Bool g_shutdown = FALSE;
static Bool redirectError = FALSE;
static Bool g_fAnotherWMRunning = FALSE;
@ -901,6 +905,11 @@ winMultiWindowXMsgProc (void *pArg)
ErrorF ("winMultiWindowXMsgProc - pthread_mutex_unlock () returned.\n");
/* Install our error handler */
XSetErrorHandler (winMultiWindowXMsgProcErrorHandler);
g_winMultiWindowXMsgProcThread = pthread_self();
g_winMultiWindowXMsgProcOldIOErrorHandler = XSetIOErrorHandler (winMultiWindowXMsgProcIOErrorHandler);
/* Set jump point for IO Error exits */
iReturn = setjmp (g_jmpXMsgProcEntry);
@ -919,10 +928,6 @@ winMultiWindowXMsgProc (void *pArg)
pthread_exit (NULL);
}
/* Install our error handler */
XSetErrorHandler (winMultiWindowXMsgProcErrorHandler);
XSetIOErrorHandler (winMultiWindowXMsgProcIOErrorHandler);
/* Setup the display connection string x */
snprintf (pszDisplay,
512, "127.0.0.1:%s.%d", display, (int)pProcArg->dwScreen);
@ -1310,6 +1315,11 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
ErrorF ("winInitMultiWindowWM - pthread_mutex_unlock () returned.\n");
/* Install our error handler */
XSetErrorHandler (winMultiWindowWMErrorHandler);
g_winMultiWindowWMThread = pthread_self();
g_winMultiWindowWMOldIOErrorHandler = XSetIOErrorHandler (winMultiWindowWMIOErrorHandler);
/* Set jump point for IO Error exits */
iReturn = setjmp (g_jmpWMEntry);
@ -1328,10 +1338,6 @@ winInitMultiWindowWM (WMInfoPtr pWMInfo, WMProcArgPtr pProcArg)
pthread_exit (NULL);
}
/* Install our error handler */
XSetErrorHandler (winMultiWindowWMErrorHandler);
XSetIOErrorHandler (winMultiWindowWMIOErrorHandler);
/* Setup the display connection string x */
snprintf (pszDisplay,
512,
@ -1458,11 +1464,17 @@ winMultiWindowWMIOErrorHandler (Display *pDisplay)
{
ErrorF ("winMultiWindowWMIOErrorHandler!\n\n");
if (g_shutdown)
pthread_exit(NULL);
if (pthread_equal(pthread_self(),g_winMultiWindowWMThread))
{
if (g_shutdown)
pthread_exit(NULL);
/* Restart at the main entry point */
longjmp (g_jmpWMEntry, WIN_JMP_ERROR_IO);
/* Restart at the main entry point */
longjmp (g_jmpWMEntry, WIN_JMP_ERROR_IO);
}
if (g_winMultiWindowWMOldIOErrorHandler)
g_winMultiWindowWMOldIOErrorHandler(pDisplay);
return 0;
}
@ -1498,8 +1510,14 @@ winMultiWindowXMsgProcIOErrorHandler (Display *pDisplay)
{
ErrorF ("winMultiWindowXMsgProcIOErrorHandler!\n\n");
/* Restart at the main entry point */
longjmp (g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO);
if (pthread_equal(pthread_self(),g_winMultiWindowXMsgProcThread))
{
/* Restart at the main entry point */
longjmp (g_jmpXMsgProcEntry, WIN_JMP_ERROR_IO);
}
if (g_winMultiWindowXMsgProcOldIOErrorHandler)
g_winMultiWindowXMsgProcOldIOErrorHandler(pDisplay);
return 0;
}