Question

I am trying GNUstep. If it's working well, I'll try to make a website with it. Anyway, I am stuck from at first. GNUstep NSRunLoop implementation doesn't seem to work well.

Here's my code.

#import <Foundation/Foundation.h>

@interface  AAA : NSObject
- (void)test1:(id)s;
@end
@implementation AAA
- (void)test1:(id)s
{
    NSLog(@"%@", s);
}
- (void)dealloc
{
    NSLog(@"DEALLOCED!!");
}
@end


int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        AAA*    aaa =   [[AAA alloc] init];
        [[NSNotificationCenter defaultCenter] addObserver:aaa selector:@selector(test1:) name:NSFileHandleDataAvailableNotification object:nil];

        [[NSFileHandle fileHandleWithStandardInput] waitForDataInBackgroundAndNotify];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

I built this code with this command.

clang -v
EE_GNUSTEP_OPTS="-MMD -MP -DGNUSTEP -DGNUSTEP_BASE_LIBRARY=1 -DGNU_RUNTIME=1 -DGNUSTEP_BASE_LIBRARY=1 -fno-strict-aliasing -fexceptions -fobjc-exceptions -D_NATIVE_OBJC_EXCEPTIONS -D_NONFRAGILE_ABI -pthread -fPIC -Wall -DGSWARN -DGSDIAGNOSE -Wno-import -g -fgnu-runtime -fconstant-string-class=NSConstantString"
EE_BUILD_OPTS="-I/usr/local/include -L/usr/local/lib -lc -lobjc -lgnustep-base -fblocks -fobjc-arc -fobjc-abi-version=3"
alias OBJCC="clang $EE_GNUSTEP_OPTS $EE_BUILD_OPTS"
OBJCC *.m

Under OSX, the program doesn't quit, and just keep running the run-loop. It worked equally under GNUstep on FreeBSD if I don't use ARC. If I enable ARC the program quit immediately. I have no idea why that doesn't work only when ARC is enabled. Why does it quits immediately?

Here's the component versions I used:

svn co http://svn.gna.org/svn/gnustep/libs/libobjc2/releases/1.7 libobjc2-1.7 &
svn co http://svn.gna.org/svn/gnustep/tools/make/tags/make-2_6_5 make-2_6_5 &
svn co http://svn.gna.org/svn/gnustep/libs/base/tags/base-1_24_5 base-1_24_5 &
Was it helpful?

Solution

This appears to be a bug in the GSFileHandle class. The singleton returned by fileHandleWithStandardInput is autoreleased. In non-ARC mode, it is destroyed at the end of the @autoreleasepool scope, but you never get to that point, so it works fine.

In ARC mode, the sequence becomes something along these lines:

    NSFileHandle *tmp = [NSFileHandle fileHandleWithStandardInput];
    objc_retainAutoreleasedReturnValue(tmp);
    [tmp waitForDataInBackgroundAndNotify];
    objc_release(tmp);

After the call to objc_release(), the object is deallocated. When the object is deallocated, it helpfully removes itself as a run loop source. The run loop then has no sources registered, and so exits (otherwise it would wait forever for nothing).

This shows one of the advantages of ARC—that temporary objects don't spend as much time in autorelease pools—but in this case it uncovers a bug. Fortunately, it uncovers the bug in a much easier-to-debug way than without ARC (without, we'd see a crash much later when something outside the current autoreleasepool scope tries to access the file handle).

I've fixed this in GNUstep Base svn r37245, thank you for the report (in the future, GNUstep bug reports are more likely to be seen if posted to the GNUstep mailing lists than to a random third-party web site, however...).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top