Se eu usar uma das funções da família exec para abrir um processo filho, os pipes para pai serão aplicados ao filho?

1

Digamos que eu abra um processo pai com um processo mestre que atribua o stdout a um arquivo para registro.

Em seguida, digamos que eu use o processo pai para abrir um filho com execvp (ou qualquer outro da família exec de funções).

De acordo com a documentação, a criança reterá o ID do processo pai .

Pergunta principal: Isso significa que o filho herdará os canais do pai (stdout e stderr especificamente)?

    
por Aaron Hall 24.09.2014 / 17:31

2 respostas

2

Para a resposta documentada, precisamos examinar a página man da chamada do sistema que a família exec de funções chama, execve :

By default, file descriptors remain open across an execve(). File descriptors that are marked close-on-exec are closed; see the description of FD_CLOEXEC in fcntl(2).

Portanto, se o processo não definiu o sinalizador close-on-exec nos descritores de arquivos dos pipes, eles permanecerão abertos após um exec.

    
por 24.09.2014 / 18:47
1

Sim, usar exec e herdar o mesmo pid como pai significa que o filho mantém as conexões de pipe por padrão, desde que os descritores de arquivo não sejam marcados como close-on-exec (o que pode ser feito via fcntl , veja a resposta de Mark Plotnick).

Eu estava à beira da auto-resposta com dados empíricos quando escrevi a minha pergunta, e segui com uma auto-resposta, então aqui está como eu fiz:

no arquivo master.py :

import subprocess
import logging

def main():
    proc = ['python', 'parent.py']
    logpath = 'parent.log'
    with open(logpath, 'ab') as f:
        p = subprocess.Popen(proc, stdout=f, stderr=subprocess.STDOUT)
        logging.warn('task started, waiting to finish')
        res = p.wait()
        logging.warn(res)

if __name__ == '__main__':
    main()

em parent.py :

import os
import logging

def main():
    proc = ['python', 'child.py']
    logging.warn('parent is logging, pid: {0}'.format(os.getpid()))
    os.execvp(proc[0], proc)

if __name__ == '__main__':
    main()

e em child.py :

import os
import logging
import time

def main():
    for i in range(2):
         logging.warn('child is logging, pid: {0}'.format(os.getpid()))
         time.sleep(15)

if __name__ == '__main__':
    main()

Quando eu executo python master.py na linha de comando, a linha de comando gera isto:

WARNING:root:task started, waiting to finish

e cerca de 15 segundos depois:

WARNING:root:0

e o arquivo parent.log contém isto:

WARNING:root:parent is logging, pid 8515
WARNING:root:child is logging, pid 8515
WARNING:root:child is logging, pid 8515

que demonstra empiricamente que o filho herda os pipes junto com o pid do pai ao usar a família exec de funções. Foi difícil encontrar documentação de suporte sobre isso, mas há um exemplo fornecido aqui (mais ou menos na metade do material.)

    
por 24.09.2014 / 17:31