* Use a dispatch queue and dispatch_async a block to handle computation. Since the queues work from a shared thread pool and are managed at the kernel level, a long-running Fib calculation won't hold up other blocks from processing on any concurrent queue (it would still hold up a sequential queue...obviously).
* Use dispatch_sources to do your IO. Now you don't have to worry about clumsy callbacks, and your IO operations are perfectly happy co-existing with your long-running computations.
* Use dispatch_read/dispatch_write to persist to disk and you don't have to worry about different latency and throughput characteristics of files vs sockets
...and to the point about signals:
* Use a signal dispatch_source to do things in response to signals that you would never have thought possible. This is possible because libdispatch sets up a trampoline to catch the actual signal and then turn around and queue your dispatch_source block. It's not a complete panacea, but it's close...
...now if only Linux would implement kqueue