зеркало из https://github.com/mozilla/pjs.git
b=499498 BadWindow errors on startup r=roc
--HG-- extra : rebase_source : 8e47f6374273fa5d44c1b3a96be5fa71f6662976
This commit is contained in:
Родитель
87d4ee061f
Коммит
d2fc5e2ab7
|
@ -1,5 +1,5 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=8:
|
||||
*/
|
||||
/* vim:set ts=8 sw=2 et cindent: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
|
@ -88,6 +88,9 @@
|
|||
|
||||
static PRLogModuleInfo *sRemoteLm = NULL;
|
||||
|
||||
static int (*sOldHandler)(Display *, XErrorEvent *);
|
||||
static PRBool sGotBadWindow;
|
||||
|
||||
XRemoteClient::XRemoteClient()
|
||||
{
|
||||
mDisplay = 0;
|
||||
|
@ -183,40 +186,10 @@ XRemoteClient::SendCommand (const char *aProgram, const char *aUsername,
|
|||
{
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommand"));
|
||||
|
||||
*aWindowFound = PR_FALSE;
|
||||
|
||||
Window w = FindBestWindow(aProgram, aUsername, aProfile, PR_FALSE);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (w) {
|
||||
// ok, let the caller know that we at least found a window.
|
||||
*aWindowFound = PR_TRUE;
|
||||
|
||||
// make sure we get the right events on that window
|
||||
XSelectInput(mDisplay, w,
|
||||
(PropertyChangeMask|StructureNotifyMask));
|
||||
|
||||
PRBool destroyed = PR_FALSE;
|
||||
|
||||
// get the lock on the window
|
||||
rv = GetLock(w, &destroyed);
|
||||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// send our command
|
||||
rv = DoSendCommand(w, aCommand, aDesktopStartupID, aResponse, &destroyed);
|
||||
|
||||
// if the window was destroyed, don't bother trying to free the
|
||||
// lock.
|
||||
if (!destroyed)
|
||||
FreeLock(w); // doesn't really matter what this returns
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("SendCommand returning 0x%x\n", rv));
|
||||
|
||||
return rv;
|
||||
return SendCommandInternal(aProgram, aUsername, aProfile,
|
||||
aCommand, 0, nsnull,
|
||||
aDesktopStartupID,
|
||||
aResponse, aWindowFound);
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -228,9 +201,39 @@ XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
|
|||
{
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("XRemoteClient::SendCommandLine"));
|
||||
|
||||
*aWindowFound = PR_FALSE;
|
||||
return SendCommandInternal(aProgram, aUsername, aProfile,
|
||||
nsnull, argc, argv,
|
||||
aDesktopStartupID,
|
||||
aResponse, aWindowFound);
|
||||
}
|
||||
|
||||
Window w = FindBestWindow(aProgram, aUsername, aProfile, PR_TRUE);
|
||||
static int
|
||||
HandleBadWindow(Display *display, XErrorEvent *event)
|
||||
{
|
||||
if (event->error_code == BadWindow) {
|
||||
sGotBadWindow = PR_TRUE;
|
||||
return 0; // ignored
|
||||
}
|
||||
else {
|
||||
return (*sOldHandler)(display, event);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
XRemoteClient::SendCommandInternal(const char *aProgram, const char *aUsername,
|
||||
const char *aProfile, const char *aCommand,
|
||||
PRInt32 argc, char **argv,
|
||||
const char* aDesktopStartupID,
|
||||
char **aResponse, PRBool *aWindowFound)
|
||||
{
|
||||
*aWindowFound = PR_FALSE;
|
||||
PRBool isCommandLine = !aCommand;
|
||||
|
||||
// FindBestWindow() iterates down the window hierarchy, so catch X errors
|
||||
// when windows get destroyed before being accessed.
|
||||
sOldHandler = XSetErrorHandler(HandleBadWindow);
|
||||
|
||||
Window w = FindBestWindow(aProgram, aUsername, aProfile, isCommandLine);
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
|
@ -238,10 +241,15 @@ XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
|
|||
// ok, let the caller know that we at least found a window.
|
||||
*aWindowFound = PR_TRUE;
|
||||
|
||||
// Ignore BadWindow errors up to this point. The last request from
|
||||
// FindBestWindow() was a synchronous XGetWindowProperty(), so no need to
|
||||
// Sync. Leave the error handler installed to detect if w gets destroyed.
|
||||
sGotBadWindow = PR_FALSE;
|
||||
|
||||
// make sure we get the right events on that window
|
||||
XSelectInput(mDisplay, w,
|
||||
(PropertyChangeMask|StructureNotifyMask));
|
||||
|
||||
|
||||
PRBool destroyed = PR_FALSE;
|
||||
|
||||
// get the lock on the window
|
||||
|
@ -249,7 +257,14 @@ XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
|
|||
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
// send our command
|
||||
rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse, &destroyed);
|
||||
if (isCommandLine) {
|
||||
rv = DoSendCommandLine(w, argc, argv, aDesktopStartupID, aResponse,
|
||||
&destroyed);
|
||||
}
|
||||
else {
|
||||
rv = DoSendCommand(w, aCommand, aDesktopStartupID, aResponse,
|
||||
&destroyed);
|
||||
}
|
||||
|
||||
// if the window was destroyed, don't bother trying to free the
|
||||
// lock.
|
||||
|
@ -259,7 +274,9 @@ XRemoteClient::SendCommandLine (const char *aProgram, const char *aUsername,
|
|||
}
|
||||
}
|
||||
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("SendCommandLine returning 0x%x\n", rv));
|
||||
XSetErrorHandler(sOldHandler);
|
||||
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("SendCommandInternal returning 0x%x\n", rv));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -338,6 +355,8 @@ XRemoteClient::GetLock(Window aWindow, PRBool *aDestroyed)
|
|||
PRBool waited = PR_FALSE;
|
||||
*aDestroyed = PR_FALSE;
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
if (!mLockData) {
|
||||
|
||||
char pidstr[32];
|
||||
|
@ -377,7 +396,16 @@ XRemoteClient::GetLock(Window aWindow, PRBool *aDestroyed)
|
|||
&actual_type, &actual_format,
|
||||
&nitems, &bytes_after,
|
||||
&data);
|
||||
if (result != Success || actual_type == None) {
|
||||
|
||||
// aWindow may have been destroyed before XSelectInput was processed, in
|
||||
// which case there may not be any DestroyNotify event in the queue to
|
||||
// tell us. XGetWindowProperty() was synchronous so error responses have
|
||||
// now been processed, setting sGotBadWindow.
|
||||
if (sGotBadWindow) {
|
||||
*aDestroyed = PR_TRUE;
|
||||
rv = NS_ERROR_FAILURE;
|
||||
}
|
||||
else if (result != Success || actual_type == None) {
|
||||
/* It's not now locked - lock it. */
|
||||
XChangeProperty (mDisplay, aWindow, mMozLockAtom, XA_STRING, 8,
|
||||
PropModeReplace,
|
||||
|
@ -387,9 +415,9 @@ XRemoteClient::GetLock(Window aWindow, PRBool *aDestroyed)
|
|||
}
|
||||
|
||||
XUngrabServer(mDisplay);
|
||||
XSync(mDisplay, False);
|
||||
XFlush(mDisplay); // ungrab now!
|
||||
|
||||
if (!locked) {
|
||||
if (!locked && !NS_FAILED(rv)) {
|
||||
/* We tried to grab the lock this time, and failed because someone
|
||||
else is holding it already. So, wait for a PropertyDelete event
|
||||
to come in, and try again. */
|
||||
|
@ -420,17 +448,16 @@ XRemoteClient::GetLock(Window aWindow, PRBool *aDestroyed)
|
|||
// did we time out?
|
||||
if (select_retval == 0) {
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("timed out waiting for window\n"));
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("xevent...\n"));
|
||||
XNextEvent (mDisplay, &event);
|
||||
if (event.xany.type == DestroyNotify &&
|
||||
event.xdestroywindow.window == aWindow) {
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
|
||||
("window 0x%x unexpectedly destroyed.\n",
|
||||
(unsigned int) aWindow));
|
||||
*aDestroyed = PR_TRUE;
|
||||
return NS_ERROR_FAILURE;
|
||||
rv = NS_ERROR_FAILURE;
|
||||
break;
|
||||
}
|
||||
else if (event.xany.type == PropertyNotify &&
|
||||
event.xproperty.state == PropertyDelete &&
|
||||
|
@ -447,13 +474,17 @@ XRemoteClient::GetLock(Window aWindow, PRBool *aDestroyed)
|
|||
}
|
||||
if (data)
|
||||
XFree(data);
|
||||
} while (!locked);
|
||||
} while (!locked && !NS_FAILED(rv));
|
||||
|
||||
if (waited) {
|
||||
if (waited && locked) {
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG, ("obtained lock.\n"));
|
||||
} else if (*aDestroyed) {
|
||||
PR_LOG(sRemoteLm, PR_LOG_DEBUG,
|
||||
("window 0x%x unexpectedly destroyed.\n",
|
||||
(unsigned int) aWindow));
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
return rv;
|
||||
}
|
||||
|
||||
Window
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
|
@ -67,6 +68,11 @@ private:
|
|||
const char *aUsername,
|
||||
const char *aProfile,
|
||||
PRBool aSupportsCommandLine);
|
||||
nsresult SendCommandInternal(const char *aProgram, const char *aUsername,
|
||||
const char *aProfile, const char *aCommand,
|
||||
PRInt32 argc, char **argv,
|
||||
const char* aDesktopStartupID,
|
||||
char **aResponse, PRBool *aWindowFound);
|
||||
nsresult DoSendCommand (Window aWindow,
|
||||
const char *aCommand,
|
||||
const char* aDesktopStartupID,
|
||||
|
|
Загрузка…
Ссылка в новой задаче