mirror of
https://github.com/gnustep/libs-back.git
synced 2025-04-23 16:10:52 +00:00
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:
parent
5125141980
commit
2e9160fd9e
2 changed files with 66 additions and 29 deletions
|
@ -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,
|
||||
|
|
88
Tools/xpbs.m
88
Tools/xpbs.m
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue