Estoy implementando una biblioteca para ejecutar comandos. La biblioteca es C, en Linux.
Actualmente realiza una llamada popen() para ejecutar un comando y obtener resultados. El problema es que el comando hereda todos los controladores de archivos abiertos actualmente.
Si hiciera un fork/exec, podría cerrar los controladores en child explícitamente. Pero eso significa volver a implementar popen().
¿Puedo configurar close-on-exec en todos los controladores sin recorrerlos uno por uno?
¿Puedo configurar close-on-exec como predeterminado para el proceso?
¡Gracias!
No y no.
Simplemente debe tener cuidado y configurar close-on-exec en todos los descriptores de archivos que le interesen.
Sin embargo, configurarlo es fácil:
#include <fcntl.h>
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
#include <unistd.h>
/* please don't do this */
for (i = getdtablesize(); i --> 3;) {
if ((flags = fcntl(i, F_GETFD)) != -1)
fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
}
Si está ejecutando el kernel de Linux ≥2.6.23 y glibc ≥2.7, open
(junto con otras llamadas al sistema similares) acepta una nueva bandera O_CLOEXEC
:
#include <unistd.h>
fd = open("...", ... | O_CLOEXEC);
Si está ejecutando kernel de Linux ≥2.6.24 y glibc ≥2.7, fcntl
acepta un nuevo argumento F_DUPFD_CLOEXEC
:
#include <fcntl.h>
newfd = fcntl(oldfd, F_DUPFD_CLOEXEC);
Si está ejecutando Linux kernel ≥2.6.27 y glibc ≥2.9, hay nuevas llamadas al sistema pipe2
, dup3
etc., y muchas más llamadas al sistema obtienen nuevos *_CLOEXEC
banderas:
#define _GNU_SOURCE
#include <unistd.h>
pipe2(pipefds, O_CLOEXEC);
dup3(oldfd, newfd, O_CLOEXEC);
Tenga en cuenta que POSIX especifica que
los popen() La función garantizará que cualquier flujo de datos anteriores popen() las llamadas que permanecen abiertas en el proceso principal se cierran en el nuevo proceso secundario.
así que si estás preocupado por que fuga, no seas.
Una pregunta un poco vieja, pero ¿qué hay del uso? getpid()
en niño después fork()
luego mira en /proc/PID/fd/
directorio y simplemente cierre todos los descriptores que encuentre allí (excepto 0, 1, 2 y el que obtiene de opendir()
) y luego execve()
?
Si recorre los descriptores de archivo, lea el directorio /proc/self/fd/ para procesar solo los que están en uso en lugar de todos los descriptores de archivo posibles.
– marca4o
31 de octubre de 2009 a las 22:10