0

Thanks in advance to anyone who is helping me.

I've a simple daemon. I allocate a class and then start a scheduled & repeating NSTimer:

[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(usage3GviaSysctl) userInfo:nil repeats:YES];

then I call CFRunLoopRun() so that my daemon will stay alive.

int main(int argc, char *argv[])
{
   NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   signal(SIGTERM, (sig_t)SIGTERM_handler);

   helper = [[NMDaemonHelper alloc] init];
   [helper startNotificationServer];
   CFRunLoopRun();

   NSLog(@"NMDAEMON: will exit");
   [pool release];
   return 0;
}

Now the problem is that after the timer fires I get a segfault. bt:

objc_msgSend
__NSFireTimer
__CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__
__CFRunLoopDoTImer
__CFRunLoopRun
CFRunLoopRunSpecific

other ways to start the timer didn't work either. for example:

NSTimer *timeUpdateTimer = [[NSTimer alloc] initWithFireDate:[NSDate date] interval:1 target:self selector:@selector(usage3GviaSysctl) userInfo:nil repeats:YES]; 
[[NSRunLoop currentRunLoop] addTimer:timeUpdateTimer forMode:NSDefaultRunLoopMode];

Has anybody an idea what's going (wr)on(g)?

YllierDev
  • 571
  • 4
  • 16

1 Answers1

0

My guess is your selector doesn't have the right format ... needs to have an NSTimer argument, so your selector has to have the ":" in it, so @selector(usage3GviaSysctl:).

... I tried it myself and seems to works so here's my code in case it was something else:

#import <Foundation/Foundation.h>

@interface NMDaemonHelper : NSObject {
    NSTimer *_aTimer;
}
- (void)startNotificationServer;
@end

@implementation NMDaemonHelper

- (void)dealloc {
    [_aTimer invalidate];
    [super dealloc];
}

- (void)startNotificationServer {
    _aTimer = [NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(usage3GviaSysctl:) userInfo:nil repeats:YES];
}

- (void)usage3GviaSysctl:(NSTimer *)aTimer {
    NSLog(@"timer fired");
}

@end

void SIGTERM_handler(int signum) {
    NSLog(@"SIGTERM_handler");
}

int main(int argc, char *argv[]) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    signal(SIGTERM, (sig_t)SIGTERM_handler);

    NMDaemonHelper *helper = [[NMDaemonHelper alloc] init];
    [helper startNotificationServer];
    CFRunLoopRun();

    [helper release];
    NSLog(@"NMDAEMON: will exit");
    [pool release];
    return 0;
}

... and output is:

pho0$ ./climac
2011-03-25 18:43:36.723 climac[2833:903] timer fired
2011-03-25 18:43:39.723 climac[2833:903] timer fired
2011-03-25 18:43:42.722 climac[2833:903] timer fired
2011-03-25 18:43:45.722 climac[2833:903] timer fired
2011-03-25 18:43:48.722 climac[2833:903] timer fired
2011-03-25 18:43:51.722 climac[2833:903] timer fired

pho0
  • 1,751
  • 16
  • 24
  • Note: Your `dealloc` won't ever be called — see _[Using Timers: Memory Management](http://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Timers/Articles/usingTimers.html#//apple_ref/doc/uid/20000807-SW6)_. – danyowdee Mar 26 '11 at 13:35
  • thank you for trying to help me. actually, I found out that this doesn't happen because of the NSTimer, but because of using sysctl in the timer's action method. This was not identify-able because crash reporter would create a false bt :( – YllierDev Mar 27 '11 at 19:33
  • @danyowdee, the dealloc is there to make this a complete implementation. This is a contrived example but if you were to use the class for real, you'd want the dealloc there. – pho0 Jul 19 '11 at 07:21
  • @pho0 that is not the point of my comment: a timer retains its target... If object `a` holds a reference to a timer which has `a` as its target, then invalidating that timer in `a`'s dealloc could be considered an implementation error: That dealloc will never be called except when you have an overrelease somewhere. – danyowdee Jul 20 '11 at 08:55