bugGNUstep - Bugs: bug #40612, NSTaskDidTerminateNotification...

 
 

You are not allowed to post comments on this tracker with your current authentification level.

bug #40612: NSTaskDidTerminateNotification posted late or never

Submitted by:  Larry Campbell <lcampbel>
Submitted on:  Sun 17 Nov 2013 09:09:25 PM UTC  
 
Category: Base/FoundationSeverity: 3 - Normal
Item Group: NoneStatus: Ready For Test
Privacy: PublicAssigned to: None
Open/Closed: In Test

Fri 20 Dec 2013 02:48:06 PM UTC, comment #3:

Thanks … the patch wasn't attached separately and wouldn't apply using cut and paste from the web page, so I implemented something that looked like it did the right thing.

I'm not sure exactly what the test code was supposed to do, so I wrapped it in a file in the testsuite (Tests/base/NSTask/notify.m), changing the subtask to be portable rather than unix-specific.

Please could you:
a. try it out and
b. update notify.m to act as a proper regression test which passes when the behavior is correct.

Richard Frith-Macdonald <CaS>
Project Member
Sun 17 Nov 2013 09:12:22 PM UTC, comment #2:

The following test function works on Mac OS X, but fails with gnustep without the fixes:

static BOOL taskTerminationNotificationReceived;

- (void)taskDidTerminate:(NSNotification *)notification
{
NSLog(@"Received NSTaskDidTerminateNotification %@", notification);
taskTerminationNotificationReceived = YES;
}

- (void)testNSTaskNotifications
{
NSDate *deadline;
BOOL earlyTermination = NO;

for (;;) {
NSTask *task = [NSTask new];
[task setLaunchPath:@"/bin/sh"];
[task setArguments:[NSArray arrayWithObjects:@"-c", @"echo Child starting; sleep 10; echo Child exiting", nil]];
taskTerminationNotificationReceived = NO;
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(taskDidTerminate:)
name: NSTaskDidTerminateNotification
object: task];
[task launch];
NSLog(@"Launched pid %d", [task processIdentifier]);
if (earlyTermination) {
NSLog(@"Running run loop for 5 seconds");
deadline = [NSDate dateWithTimeIntervalSinceNow:5.0];
while ([deadline timeIntervalSinceNow] > 0.0)
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
NSLog(@"Run loop finished, will now call -[NSTask terminate]");
[task terminate];
NSLog(@"Terminate returned, waiting for termination");
[task waitUntilExit];
} else {
NSLog(@"Running run loop for 15 seconds");
deadline = [NSDate dateWithTimeIntervalSinceNow:15.0];
while ([deadline timeIntervalSinceNow] > 0.0 && !taskTerminationNotificationReceived)
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];
}
[task release];
NSAssert(taskTerminationNotificationReceived, @"termination notification not received");
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSTaskDidTerminateNotification object:nil];
if (earlyTermination)
break;
earlyTermination = YES;
}
}

Larry Campbell <lcampbel>
Sun 17 Nov 2013 09:10:51 PM UTC, comment #1:

Fixes (based on gnustep 1.24.0):

      • NSRunLoop.m.orig Sun Nov 17 19:48:08 2013

--- NSRunLoop.m Sun Nov 17 20:03:44 2013
***************

      • 1240,1245 ****

--- 1240,1248 ----

NSAssert(mode != nil, NSInvalidArgumentException);

+ GSPrivateCheckTasks();
+ GSPrivateNotifyASAP(mode);
+
/* Find out how long we can wait before first limit date. */
d = [self limitDateForMode: mode];
if (d == nil)

      • NSTask.m.orig Sun Nov 17 18:18:09 2013

--- NSTask.m Sun Nov 17 20:47:04 2013
***************

      • 855,862 ****

- (void) waitUntilExit
{
NSTimer *timer = nil;

! while ([self isRunning])
{
NSDate *limit;

--- 855,865 ----
- (void) waitUntilExit
{
NSTimer *timer = nil;
+ int extra = 1; // call run loop once more after termination so notifications are posted promptly

! IF_NO_GC([[self retain] autorelease];) // in case notification releases self
!
! while ([self isRunning] || extra-- > 0)
{
NSDate *limit;

Larry Campbell <lcampbel>
Sun 17 Nov 2013 09:09:25 PM UTC, original submission:

NSTaskDidTerminateNotification is sometimes posted late or never. It is not posted if the current run loop has no input sources or timers. On Mac OS X, it is posted regardless of whether the run loop has input sources or timers. Further, on Mac OS X if you call -[NSTask waitUntilExit] your notifications will be posted before waitUntilExit returns; on gnustep it will only be posted later (the next time a run loop with timers or input sources is entered).

Larry Campbell <lcampbel>

 

No files currently attached

 

Depends on the following items: None found

Items that depend on this one: None found

 

Carbon-Copy List
  • -unavailable- added by CaS (Posted a comment)
  • -unavailable- added by lcampbel (Submitted the item)
  •  

    Do you think this task is very important?
    If so, you can click here to add your encouragement to it.
    This task has 0 encouragements so far.

    Only logged-in users can vote.

     

    Please enter the title of George Orwell's famous dystopian book (it's a date):

     

     

    Follow 2 latest changes.

    Date Changed By Updated Field Previous Value => Replaced By
    Fri 20 Dec 2013 02:48:06 PM UTCCaSStatusNone=>Ready For Test
      Open/ClosedOpen=>In Test

    Back to the top


    Powered by Savane 3.1-cleanup