Я ищу подход для обнаружения закрытия приложения (например, cmd-q) в пространстве ядра для обработки в расширении сетевого ядра.Как обнаружить завершение приложения в расширении ядра, Mac OS X
Точнее: Хотя процесс (например, терминал ping) хранится в IOLockSleep (... THREAD_ABORTSAFE), ctrl-c может освободить блокировку. Спрашивая proc_issignal(), он отвечает на сигмаску (SIGINT).
Теперь я ищу способ обнаружить другой процесс, например, firefox (строка меню: приложение quit (cmd-q)).
Вот что я пробовал:
#define FLAG(X) ((dispatch_source_get_data(src) & DISPATCH_PROC_##X) ? #X" " : "")
struct ProcessInfo {
int pid;
dispatch_source_t source;
};
// function called back on event
void process_termination_event(struct ProcessInfo* procinfo) {
dispatch_source_t src = procinfo->source;
printf("process_termination_event: %d \n", procinfo->pid);
printf("flags: %s%s\n", FLAG(EXIT), FLAG(SIGNAL));
dispatch_source_cancel(procinfo->source);
}
// function called back when the dispatch source is cancelled
void process_termination_finalize(struct ProcessInfo* procinfo) {
printf("process_termination_finalize: %d \n", procinfo->pid);
dispatch_release(procinfo->source);
}
// Monitor a process by pid, for termination
void MonitorTermination(int pid) {
struct ProcessInfo* procinfo = (struct ProcessInfo*)malloc(sizeof(struct ProcessInfo));
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t dsp = dispatch_source_create(DISPATCH_SOURCE_TYPE_PROC, pid, DISPATCH_PROC_EXIT|DISPATCH_PROC_SIGNAL, queue);
procinfo->pid = pid;
procinfo->source = dsp;
dispatch_source_set_event_handler_f(procinfo->source, (dispatch_function_t)process_termination_event);
dispatch_source_set_cancel_handler_f(procinfo->source, (dispatch_function_t)process_termination_finalize);
dispatch_set_context(procinfo->source, procinfo);
dispatch_resume(procinfo->source);
}
int main(int argc, const char * argv[])
{
for (int i = 0; i < argc; ++i) {
pid_t pid = atoi(argv[i]);
printf("MonitorTermination: %d\n", pid);
fflush(stdout);
MonitorTermination(pid);
}
CFRunLoopRun();
return 0;
}
process_termination_event не будет вызывать после CMD-ц, как описано выше. Даже после того, как сила ушла.
Сам процесс проходит в цикле в функции сетевого расширения ядра:
errno_t KEXT::data_out(void *cookie, socket_t so, const struct sockaddr *to, mbuf_t *data, mbuf_t *control, sflt_data_flag_t flags)
{
// at this point I would like to detect the app quit/termination signal.
while(PROCESS_IS_NOT_TEMINATING); // <-- pseudo code, actually held with IOLockSleep...
return 0;
}
Я был бы очень признателен за любую помощь! Заранее спасибо.
Подход хороший. Но я застрял с проблемой «завершение работы приложения». Поскольку функция kext сохраняет приложение в активном режиме. Приложение не может завершиться до завершения обработки kext. – Jan
Если вы реализовали то, что я описал, не должно быть никаких проблем с завершением приложения - я все время использую это. Расширение ядра делает не что иное, как уведомление демона активности процесса, оно не должно содержать никаких ресурсов процесса. – TheDarkKnight
Я думаю, что я реализовал, как описано. Теперь я добавил более подробное описание и код демона. Может быть, что-то не так, или обработка kext (в то время как цикл/блокировка) совсем не соответствует намерению? – Jan