実際、DISPATCH_VNODE_DELETE を受け取ったときに、ファイルを再度開いてソースを再登録する (前のソースを削除する) ことができます。または、この種のシナリオ用に考案された呼び出し、つまりdispatch_io_create_with_path()を使用できます。これは、パスで監視するだけでなく、ファイルを開き、内容を非同期で読み取ることができます。
あなたが尋ねたので(あなたが求めたテクニックはわかりませんが、これが最も簡単です)、スタンドアロンのコードサンプルを次に示します。
#include <dispatch/dispatch.h>
#include <stdio.h>
int main(int ac, char *av[])
{
int fdes = open("/tmp/pleasewatchthis", O_RDONLY);
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
void (^eventHandler)(void), (^cancelHandler)(void);
unsigned long mask = DISPATCH_VNODE_DELETE | DISPATCH_VNODE_WRITE | DISPATCH_VNODE_EXTEND | DISPATCH_VNODE_ATTRIB | DISPATCH_VNODE_LINK | DISPATCH_VNODE_RENAME | DISPATCH_VNODE_REVOKE;
__block dispatch_source_t source;
eventHandler = ^{
unsigned long l = dispatch_source_get_data(source);
if (l & DISPATCH_VNODE_DELETE) {
printf("watched file deleted! cancelling source\n");
dispatch_source_cancel(source);
}
else {
// handle the file has data case
printf("watched file has data\n");
}
};
cancelHandler = ^{
int fdes = dispatch_source_get_handle(source);
close(fdes);
// Wait for new file to exist.
while ((fdes = open("/tmp/pleasewatchthis", O_RDONLY)) == -1)
sleep(1);
printf("re-opened target file in cancel handler\n");
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE, fdes, mask, queue);
dispatch_source_set_event_handler(source, eventHandler);
dispatch_source_set_cancel_handler(source, cancelHandler);
dispatch_resume(source);
};
source = dispatch_source_create(DISPATCH_SOURCE_TYPE_VNODE,fdes, mask, queue);
dispatch_source_set_event_handler(source, eventHandler);
dispatch_source_set_cancel_handler(source, cancelHandler);
dispatch_resume(source);
dispatch_main();
}