Add warning message if stuck waiting for a response for over 5 min

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@28621 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
rfm 2009-09-07 11:29:50 +00:00
parent c666d14923
commit 47f75d034c

View file

@ -2878,9 +2878,11 @@ static void callEncoder (DOContext *ctxt)
NSPortCoder *rmc = nil; NSPortCoder *rmc = nil;
GSIMapNode node = 0; GSIMapNode node = 0;
NSDate *timeout_date = nil; NSDate *timeout_date = nil;
NSTimeInterval last_interval = 0.0001; NSTimeInterval delay_interval = 0.0;
NSTimeInterval delay_interval = last_interval; NSTimeInterval last_interval;
NSTimeInterval maximum_interval;
NSDate *delay_date = nil; NSDate *delay_date = nil;
NSDate *start_date = nil;
NSRunLoop *runLoop; NSRunLoop *runLoop;
BOOL isLocked = NO; BOOL isLocked = NO;
@ -2910,6 +2912,28 @@ static void callEncoder (DOContext *ctxt)
} }
} }
if (_multipleThreads == YES)
{
/* Since multiple threads are using this connection, another
* thread may read the reply we are waiting for - so we must
* break out of the runloop frequently to check. We do this
* by setting a small delay and increasing it each time round
* so that this semi-busy wait doesn't consume too much
* processor time (I hope).
* We set an upper limit on the delay to avoid responsiveness
* problems.
*/
last_interval = 0.0001;
maximum_interval = 1.0;
}
else
{
/* As the connection is single threaded, we can wait indefinitely
* for a response ... but we recheck every five minutes anyway.
*/
last_interval = maximum_interval = 300.0;
}
NS_DURING NS_DURING
{ {
if (debug_connection > 5) if (debug_connection > 5)
@ -2920,33 +2944,23 @@ static void callEncoder (DOContext *ctxt)
&& (node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn)) != 0 && (node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn)) != 0
&& node->value.obj == dummyObject) && node->value.obj == dummyObject)
{ {
NSDate *limit_date;
M_UNLOCK(_queueGate); isLocked = NO; M_UNLOCK(_queueGate); isLocked = NO;
if (timeout_date == nil) if (start_date == nil)
{ {
start_date = [dateClass allocWithZone: NSDefaultMallocZone()];
start_date = [start_date init];
timeout_date = [dateClass allocWithZone: NSDefaultMallocZone()]; timeout_date = [dateClass allocWithZone: NSDefaultMallocZone()];
timeout_date timeout_date
= [timeout_date initWithTimeIntervalSinceNow: _replyTimeout]; = [timeout_date initWithTimeIntervalSinceNow: _replyTimeout];
} }
if (_multipleThreads == YES)
{
NSDate *limit_date;
NSTimeInterval next_interval;
/*
* If multiple threads are using this connections, another
* thread may read the reply we are waiting for - so we must
* break out of the runloop frequently to check. We do this
* by setting a small delay and increasing it each time round
* so that this semi-busy wait doesn't consume too much
* processor time (I hope).
* We set an upper limit on the delay to avoid responsiveness
* problems.
*/
RELEASE(delay_date); RELEASE(delay_date);
delay_date = [dateClass allocWithZone: NSDefaultMallocZone()]; delay_date = [dateClass allocWithZone: NSDefaultMallocZone()];
if (delay_interval < 1.0) if (delay_interval < maximum_interval)
{ {
next_interval = last_interval + delay_interval; NSTimeInterval next_interval = last_interval + delay_interval;
last_interval = delay_interval; last_interval = delay_interval;
delay_interval = next_interval; delay_interval = next_interval;
} }
@ -2981,20 +2995,10 @@ static void callEncoder (DOContext *ctxt)
node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn); node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn);
break; break;
} }
} else if (_multipleThreads == NO)
}
else
{ {
/* NSLog(@"WARNING ... waiting for reply %u since %@ on %@",
* Normal operation - wait for data or for a timeout. sn, start_date, self);
*/
if ([runLoop runMode: NSConnectionReplyMode
beforeDate: timeout_date] == NO
|| [timeout_date timeIntervalSinceNow] <= 0.0)
{
M_LOCK(_queueGate); isLocked = YES;
node = GSIMapNodeForKey(_replyMap, (GSIMapKey)sn);
break;
} }
} }
M_LOCK(_queueGate); isLocked = YES; M_LOCK(_queueGate); isLocked = YES;
@ -3009,6 +3013,7 @@ static void callEncoder (DOContext *ctxt)
GSIMapRemoveKey(_replyMap, (GSIMapKey)sn); GSIMapRemoveKey(_replyMap, (GSIMapKey)sn);
} }
M_UNLOCK(_queueGate); isLocked = NO; M_UNLOCK(_queueGate); isLocked = NO;
TEST_RELEASE(start_date);
TEST_RELEASE(delay_date); TEST_RELEASE(delay_date);
TEST_RELEASE(timeout_date); TEST_RELEASE(timeout_date);
if (rmc == nil) if (rmc == nil)