Sí, de forma predeterminada cada vez que bifurca un proceso (que system
hace), el elemento secundario hereda todos los descriptores de archivos del elemento principal. Si el niño no necesita esos descriptores, DEBERÍA cerrarlos. La forma de hacerlo con system
(o cualquier otro método que haga un fork + exec) es establecer el indicador FD_CLOEXEC en todos los descriptores de archivo que no deberían ser utilizados por los hijos del proceso. Esto hará que se cierren automáticamente cada vez que un niño ejecute algún otro programa.
En general, CUALQUIER TIEMPO su programa abre CUALQUIER TIPO de descriptor de archivo que vivirá durante un período prolongado (como un socket de escucha en su ejemplo) y que no se debe compartir con niños, debe hacer
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
en el descriptor de archivo.
A partir del 2016? revisión de POSIX.1, puede utilizar la bandera SOCK_CLOEXEC
usando OR en el tipo de la toma para conseguir este comportamiento de forma automática cuando se crea el socket:
listenfd = socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, 0);
bind(listenfd, ...
listen(listemfd, ...
cuales guarentees que se cerrará correctamente, incluso si algún otro Al ejecutar simultáneamente hilo hace una llamada system
o fork
+ exec
. Afortunadamente, esta bandera ha sido admitida por un tiempo en Linux y unixes BSD (pero no en OSX, desafortunadamente).
Sí, me encontré con esto. Hasta el momento en que cambie mi código para usar fork()/exec() usaré este método solamente. –
Con POSIX 2008 o GNU, también puede usar el indicador 'O_CLOEXEC' al abrir el archivo. Esto evita tener que hacer una llamada por separado, y hace que la operación * atómica *, que importa si otro hilo (o controlador de señal) podría fork-and-exec entre la llamada 'open' y la llamada' fcntl'. –