3

I am trying to make a console window in my OS X application, which is basically displaying the content of the application log file stored in ~/Library/Application Support/CocosBuilder/cocosbuilder.log

I redirected all NSLog statement from my application inside this file:

+ (void)redirectNSLogToDocumentFolder
{
    NSString *logFilePath = [self logfilePath];
    freopen([logFilePath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}

Then I watch for modifications in the folder:

- (void)subscribeFileSystemChanges
{
    NSString* _pathToObserve = [ConsoleWindow logfileDir];
    NSArray * pathArray = [NSArray arrayWithObject:_pathToObserve];

    // if already subscribed then unsubscribe
    if (stream)
    {
        FSEventStreamStop(stream);
        FSEventStreamInvalidate(stream);
        FSEventStreamRelease(stream);
    }

    FSEventStreamContext context;
    context.info = (__bridge void *)self;
    context.version = 0;
    context.retain = NULL;
    context.release = NULL;
    context.copyDescription = NULL;

    stream = FSEventStreamCreate(kCFAllocatorDefault,
                                 (FSEventStreamCallback)refreshConsoleTextView,
                                 &context,
                                 (__bridge CFArrayRef)pathArray,
                                 kFSEventStreamEventIdSinceNow,
                                 1.0,
                                 kFSEventStreamCreateFlagWatchRoot);

    FSEventStreamScheduleWithRunLoop(stream, CFRunLoopGetCurrent(),
                                     kCFRunLoopDefaultMode);

    FSEventStreamStart(stream);
}

My callback method refreshConsoleTextView is called when I add something to my log file from terminal with:

echo "toto" >> cocosbuilder.log 

But it's not called when my own application writes something to they log file (with my NSLog redirection). I did not use the flag kFSEventStreamCreateFlagIgnoreSelf

Do you have any idea ?

  • Have you verified that your application's log statements have actually written to the file on disk? Reopening stderr may result in it being block buffered rather than unbuffered (as it was initially). You could setting your new `stderr` to unbuffered using `setbuf(stderr, NULL)`. Other things: use `-fileSystemRepresentation`, not `-cStringUsingEncoding:`. The `context` should use `CFRetain`, `CFRelease`, and `CFCopyDescription` for the relevant callbacks. – Ken Thomases Mar 27 '16 at 13:27
  • Yes, a "tail -f" on the log file in terminal shows the addition made by NSLog(). I'll try your suggestions, I'll tell you if it changes something – Olivier PIERRE Mar 27 '16 at 14:01
  • Well, the other suggestions were just general code improvements. I don't expect them to change the behavior. – Ken Thomases Mar 27 '16 at 14:15
  • The issue may have to do with when the file is closed. The shell command will open and close the file for just that command. Your `stderr` won't be closed until the process exits. What happens if, in the shell, you do `exec 3>>cocosbuilder.log ; echo "toto" >&3`? Does your callback get called? What if you later either close that shell or do `exec 3>&-`? – Ken Thomases Mar 27 '16 at 14:25

0 Answers0