Fix race condition where gpbs could time out waiting for a property

change notification from the X server, which is already present in the
X event queue.


git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/back/trunk@32457 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Wolfgang Lux 2011-03-05 14:40:22 +00:00
parent 5125141980
commit 2e9160fd9e
2 changed files with 66 additions and 29 deletions

View file

@ -1,3 +1,10 @@
2011-03-05 Wolfgang Lux <wolfgang.lux@gmail.com>
* Tools/xpbs.m (+xEvent:, +receivedEvent:type:extra:,
-requestData:, -xTimeByAppending): Fix race condition where gpbs
could time out waiting for a property change notification from the
X server, which is already present in the X event queue.
2011-02-15 Fred Kiefer <FredKiefer@gmx.de>
* Source/win32/WIN32Server.m,

View file

@ -143,6 +143,7 @@ static Atom atoms[sizeof(atom_names)/sizeof(char*)];
+ (NSDate*) timedOutEvent: (void*)data
type: (RunLoopEventType)type
forMode: (NSString*)mode;
+ (void) xEvent: (XEvent *)xEvent;
+ (void) xPropertyNotify: (XPropertyEvent*)xEvent;
+ (void) xSelectionClear: (XSelectionClearEvent*)xEvent;
+ (void) xSelectionNotify: (XSelectionEvent*)xEvent;
@ -326,8 +327,8 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
#if 0
/* Don't attempt to be smart here. We may enter this method recursively
* when further data is requested while processing this event, which
* means that the count will not longer be correct when returning to
* the outer invocation.
* means that the count will no longer be correct when returning to the
* outer invocation.
*/
while (count-- > 0)
#endif
@ -335,33 +336,7 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
XEvent xEvent;
XNextEvent(xDisplay, &xEvent);
switch (xEvent.type)
{
case PropertyNotify:
[self xPropertyNotify: (XPropertyEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"PropertyNotify.");
break;
case SelectionNotify:
[self xSelectionNotify: (XSelectionEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"SelectionNotify.");
break;
case SelectionClear:
[self xSelectionClear: (XSelectionClearEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"SelectionClear.");
break;
case SelectionRequest:
[self xSelectionRequest: (XSelectionRequestEvent*)&xEvent];
NSDebugLLog(@"Pbs", @"SelectionRequest.");
break;
default:
NSDebugLLog(@"Pbs", @"Unexpected X event.");
break;
}
[self xEvent: &xEvent];
}
}
}
@ -379,6 +354,36 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
#define FULL_LENGTH 8192L /* Amount to read */
+ (void) xEvent: (XEvent *)xEvent
{
switch (xEvent->type)
{
case PropertyNotify:
NSDebugLLog(@"Pbs", @"PropertyNotify.");
[self xPropertyNotify: &xEvent->xproperty];
break;
case SelectionNotify:
NSDebugLLog(@"Pbs", @"SelectionNotify.");
[self xSelectionNotify: &xEvent->xselection];
break;
case SelectionClear:
NSDebugLLog(@"Pbs", @"SelectionClear.");
[self xSelectionClear: &xEvent->xselectionclear];
break;
case SelectionRequest:
NSDebugLLog(@"Pbs", @"SelectionRequest.");
[self xSelectionRequest: &xEvent->xselectionrequest];
break;
default:
NSDebugLLog(@"Pbs", @"Unexpected X event.");
break;
}
}
+ (void) xSelectionClear: (XSelectionClearEvent*)xEvent
{
XPbOwner *o;
@ -586,9 +591,21 @@ static NSString *xWaitMode = @"XPasteboardWaitMode";
/*
* Run an event loop to read X events until we have aquired the
* pasteboard data we need.
* However, before entering the event loop be sure to drain the X event
* queue, since XFlush may read events from the X connection and thus
* may have enqueued our expected property change notification in the
* X event queue already.
*/
limit = [NSDate dateWithTimeIntervalSinceNow: 20.0];
[self setWaitingForSelection: whenRequested];
while (XQLength(xDisplay) > 0 &&
[self waitingForSelection] == whenRequested)
{
XEvent xEvent;
XNextEvent(xDisplay, &xEvent);
[[self class] xEvent: &xEvent];
}
while ([self waitingForSelection] == whenRequested)
{
[[NSRunLoop currentRunLoop] runMode: xWaitMode
@ -992,6 +1009,8 @@ xErrorHandler(Display *d, XErrorEvent *e)
BOOL status;
status = [self xProvideSelection: xEvent];
if (!status)
NSDebugLLog(@"Pbs", @"Could not provide selection upon request.");
/*
* Set up the selection notify information from the event information
@ -1420,7 +1439,18 @@ xErrorHandler(Display *d, XErrorEvent *e)
/*
* Run an event loop until we get a notification for our nul append.
* this will give us an up-to-date timestamp as required by ICCCM.
* However, before entering the event loop be sure to drain the X event
* queue, since XFlush may read events from the X connection and thus may
* have enqueued our expected property change notification in the X event
* queue already.
*/
while (XQLength(xDisplay) && [self timeOfLastAppend] == 0)
{
XEvent xEvent;
XNextEvent(xDisplay, &xEvent);
[[self class] xEvent: &xEvent];
}
while ([self timeOfLastAppend] == 0)
{
[[NSRunLoop currentRunLoop] runMode: xWaitMode