Estoy escribiendo una aplicación que inicia un subproceso que ejecuta un servidor web simple. Estoy usando NSTask y comunicándome con él con tuberías, y todo parece más o menos correcto. Sin embargo, si mi programa falla, el subproceso se deja con vida y la próxima vez que inicie la aplicación hay un conflicto entre el antiguo subproceso y el nuevo. ¿Hay alguna manera de asegurar que los subprocesos mueran cuando la aplicación propietaria muere?Asegurar que un subproceso está muerto en Cocoa
Respuesta
Su delegado aplicación puede poner en práctica el mensaje
- (void)applicationWillTerminate:(NSNotification *)aNotification
, y terminar el NSTask allí. Sin embargo, no se garantiza que durante un choque se llame a este delegado.
dos pasos adicionales que puede tomar:
- apagado una ya existente, subproceso huérfanos durante el lanzamiento de un nuevo padre-proceso por escribir en el disco el PID del subproceso de creación y retirarlo durante el cierre normal de (a veces no es el comportamiento más seguro).
- Apague el subproceso si el punto final de la NSPipe no envió datos durante un período de tiempo específico (algo así como un latido del corazón).
ACTUALIZACIÓN: Ahora que voy a comprobar esto correctamente, no funciona. Intentando configurar el grupo de proceso falla con este error;
EPERM "La identificación de usuario efectiva del proceso solicitado es diferente de la de la persona que llama y el proceso no es un descendiente del proceso de llamada."
hay un hilo más reciente sobre este tema, pero hay una solución fácil por lo que yo puedo decir
http://www.omnigroup.com/mailman/archive/macosx-dev/2009-March/062164.html
He intentado una sugerencia de Robert Pointon en Cocoadev en mi aplicación. Aunque aún no llegué a probarlo.
http://www.cocoadev.com/index.pl?NSTaskTermination
La idea es establecer el grupo de procesos de la tarea a ser el mismo que el del proceso que inicia la tarea (nota: el código de abajo es, básicamente, levantada del hilo anterior).
pid_t group = setsid();
if (group == -1) {
group = getpgrp();
}
[task launch];
if (setpgid([task processIdentifier], group) == -1) {
NSLog(@"unable to put task into same group as self");
[task terminate];
} else {
// handle running task
}
Nada de lo anterior funciona ... Ni siquiera launchd
en toda su crappily-documentada complejidad tiene una manera de manejar esta situación común. No sé por qué Apple no se limita a hacer una forma "nodriza aprobados" para ejecutar procesos en segundo plano, pero lo que sea .. mi solución es ...
lanzamiento a través de un script de shell NSTask y pasarlo cualquier variable que necesita. también pasan en su proceso padre PID través
int masterPID = [[NSProcessInfo processInfo] processIdentifier];
etc. Lea estos en su secuencia de comandos a través de $ 1, $ 2, etc.A su vez, poner en marcha sus procesos parciales de dentro de la secuencia de comandos ..
Supervise el subproceso Y su proceso primario dentro del script.
Esto tiene un doble propósito .. que le permite "mantener un ojo en los niños ..", y en el triste caso de parentcide (o un accidente automovilístico horrible) - Kill-off los huérfanos zombi. Luego, aprieta el gatillo usted mismo (siendo el script de shell) y su tabla de procesos estará limpia .. como si nunca hubiera existido. Sin puertos bloqueados, sin conflictos en el relanzamiento, sin rechazos de la tienda de aplicaciones. ¡Déjame saber si esto ayuda!
Actualización: Hice una plantilla/daemon/proyecto de Xcode/lo que sea que haga el truco. Verifíquelo ... mralexgray/Infanticide.
El siguiente ejemplo de código debería ayudarlo.
que es tomado de here,
#include <CoreFoundation/CoreFoundation.h>
#include <unistd.h>
#include <sys/event.h>
static void noteProcDeath(CFFileDescriptorRef fdref, CFOptionFlags callBackTypes, void *info) {
struct kevent kev;
int fd = CFFileDescriptorGetNativeDescriptor(fdref);
kevent(fd, NULL, 0, &kev, 1, NULL);
// take action on death of process here
printf("process with pid '%u' died\n", (unsigned int)kev.ident);
CFFileDescriptorInvalidate(fdref);
CFRelease(fdref); // the CFFileDescriptorRef is no longer of any use in this example
}
// one argument, an integer pid to watch, required
int main(int argc, char *argv[]) {
if (argc < 2) exit(1);
int fd = kqueue();
struct kevent kev;
EV_SET(&kev, atoi(argv[1]), EVFILT_PROC, EV_ADD|EV_ENABLE, NOTE_EXIT, 0, NULL);
kevent(fd, &kev, 1, NULL, 0, NULL);
CFFileDescriptorRef fdref = CFFileDescriptorCreate(kCFAllocatorDefault, fd, true, noteProcDeath, NULL);
CFFileDescriptorEnableCallBacks(fdref, kCFFileDescriptorReadCallBack);
CFRunLoopSourceRef source = CFFileDescriptorCreateRunLoopSource(kCFAllocatorDefault, fdref, 0);
CFRunLoopAddSource(CFRunLoopGetMain(), source, kCFRunLoopDefaultMode);
CFRelease(source);
// run the run loop for 20 seconds
CFRunLoopRunInMode(kCFRunLoopDefaultMode, 20.0, false);
return 0;
}
- 1. ¿IronRuby está muerto?
- 2. ¿Está cgi muerto?
- 3. ¿Log4net está muerto?
- 4. ¿WAP está muerto?
- 5. ¿Está GLUT muerto?
- 6. ¿COM está muerto?
- 7. ¿Linq2XSD está muerto?
- 8. ¿El proyecto utrace está muerto?
- 9. ¿Está muerto el framework Tao?
- 10. ¿Se está ejecutando un subproceso en iOS?
- 11. carriles - www Asegurar está en la URL
- 12. XSL: Muerto o no muerto
- 13. NET Remoting y MarshalByRefObject está realmente muerto?
- 14. ¿El editor visual de eclipse está muerto?
- 15. ¿Cuándo un punto muerto no es un punto muerto?
- 16. java.lang.RuntimeException: ¿el servidor del sistema está muerto?
- 17. ¿El marco de rayas está muerto? ¿Alguien lo está usando?
- 18. Si SOA está muerto, ¿qué lo está reemplazando?
- 19. QObject: No se puede crear hijos para un padre que está en un subproceso diferente
- 20. Transacción de Mysql en espera de bloqueo que ya está otorgado .. Esto está causando un punto muerto
- 21. ¿Está seguro el subproceso RNGCryptoServiceProvider.GetBytes?
- 22. ¿Cómo matar un subproceso en Java que está en estado EN EJECUCIÓN?
- 23. ¿Está MVVM muerto en Windows 8 Store Apps?
- 24. Cómo depurar un punto muerto en Java usando Eclipse
- 25. Punto muerto en ThreadPoolExecutor
- 26. ¿Cómo puede encontrar el número de procesador en el que se está ejecutando un subproceso?
- 27. Android: ¿puede AsyncTask regresar en otro subproceso que el subproceso de interfaz de usuario?
- 28. Cómo causar un punto muerto
- 29. Delphi - ¿Está seguro el subproceso TClientDataset?
- 30. NSRunLoop del subproceso principal al que se hace referencia en un subproceso secundario
¿Ha intentado hacer su programa se cuelga? : D – kubi
Estoy pensando en Atlas aquí ^^ –
Puede intentar ejecutar el servidor web en Launchd. Al menos de esa manera, cuando su aplicación falla y se reinicia, Launchd le dirá que el servidor ya se está ejecutando, por lo que puede cerrarlo y reiniciarlo si lo desea. –