2010-02-03 11 views
10

Ho un processo figlio che gira in uno pseudo terminale. Il processo genitore non viene eseguito come root, ma il processo figlio esegue, tramite su o sudo. Per questo motivo non è possibile inviare un segnale al processo figlio per forzarlo ad uscire. Voglio forzarlo ad uscire con uno di questi mezzi:Come inviare il carattere di controllo Ctrl-C o il messaggio di blocco del terminale al processo figlio?

  • emulare un Ctrl-C.
  • emulazione di un hangup del terminale.

Come si esegue uno di questi? Ho già un maestro fd pty, e ho provato qualcosa di simile:

write(master, &termios.c_cc[VINTR], 1) 

ma non fa nulla.

+0

Non so se questo funzionerà con il programma/pty, ma cosa faccio dato che sto eseguendo bash, e bash accetta^C come SIGINT di default [Penso che?] Sia un char che contiene un codice esadecimale: (0x03 per^C) e quindi scriverlo sul mio pty con: write (m_nMaster, & ctrlC, sizeof (ctrlC)); –

risposta

2

alla fine ho andato con la seguente soluzione:

Dopo forking, invece di exec'ing immediatamente sudo, ho Exec un processo figlio() helper, invece, che a sua volta forchette e dirigenti sudo e chiede waitpid su di esso. Così la gerarchia processo assomiglia a questo:

original process   <---- runs as user 
    | 
    +-- helper process  <---- runs as user, session leader, 
     |      has own pty, in pty's foreground process group 
     | 
     +--- sudo  <---- runs as root 

Uccidendo il processo di aiuto, il PTY non ha più un processo in primo piano. Questo farà sì che il SO invii SIGHUP all'intero gruppo di processi in primo piano, indipendentemente dall'utente, quindi sudo è SIGHUP.

0

Ci sono due modi per raggiungere questo obiettivo:

  • Dal processo figlio, trappola il segnale SIGCHLD e gestirlo, si potrebbe _exit (0) per terminare il processo figlio
  • C'è un programma chiamato ptree . Si potrebbe imbrogliare questo facendo in questo modo ... in pseudocodice:
 
obtain the parent's pid. 
using _popen("ptree %d", parent_pid) 
for each entry of child process 
system ("kill -1 %d", child_process_pid) 

Vi i due che viene in mente ... scusa se non di più aiutare a voi,

Spero che questo aiuta, Cordiali saluti, Tom.

+0

Non può segnalare direttamente il bambino perché è in esecuzione con un diverso uid effettivo. – caf

+0

@caf: hmmm .... puoi rispondere a questo? immagina se il processo figlio è in esecuzione su uno pseudo terminale, prendi questo sotto un esempio di linux ... se un file binario dovesse essere catalogato con lo pseudo terminale, dire/dev/pty4 dove si trova il processo figlio, ciò causerebbe un arresto del terminale? cioè cat binary_file>/dev/pty4 – t0mm13b

+0

No, perché dovrebbe? Fornirà solo quei byte al lato master della coppia di terminali pseudo. – caf

0

La chiusura del master dovrebbe segnalare un blocco al gruppo di controllo dello slave.

0

Penso che sia necessario utilizzare ioctl per inserire il carattere di interruzione anziché write. Sfortunatamente il meccanismo per questo non sembra essere portatile. Per linux sembra questo potrebbe funzionare:

ioctl(master, TIOCSTI, &termios.c_cc[VINTR]); 
+0

Viene visualizzato un errore "permesso negato"/"operazione non consentita". Se eseguo il processo come root, viene visualizzato "timeout dell'operazione". – Hongli

0

La prima cosa che vorrei verificare è se è necessario rendere il terminale di controllo sul lato slave. Si scopre che questo è more complex di quanto ricordo, con i ptys che probabilmente non stanno diventando controllando di default. Questo collegamento è per Linux, altri sistemi dovrebbero fare l'uno o l'altro a seconda del loro SysV rispetto a BSD-ness, ma sembra che TIOCSCTTY sia una buona scommessa da provare.

In secondo luogo, controllerei se si sta impostando l'ISIG nei propri termios; in caso contrario, VINTR e VQUIT non funzioneranno.

Ovviamente, se l'altra estremità sta intercettando SIGINT e SIGQUIT, si avranno altri problemi.

4

Mi sembra che se si ha veramente un pty (a meno che non si intenda qualcos'altro da pseudo terminale), tutto ciò che si deve fare è inviare un Control-C a quel FD. A riprova di ciò, a mio avviso il seguente codice in Python (ma abbastanza vicino al C tenuto a farlo):

import pty, os, sys, time 

pid, fd = pty.fork() 
if pid == 0: 
    os.execv('/bin/sh', ['/bin/sh', '-c', 
     'while true; do date; sleep 1; done']) 
    sys.exit(0) 
time.sleep(3) 
os.write(fd, '^C') 
print 'results:', os.read(fd, 1024) 

Questo forche un processo in un pty, che gestisce un ciclo infinito stampa della data . Quindi il genitore attende 3 secondi e invia un controllo-C.

Il risultato è il seguente output:

guin:/tmp$ time python /tmp/foo 
results: Fri Feb 5 08:28:09 MST 2010 
Fri Feb 5 08:28:10 MST 2010 
Fri Feb 5 08:28:11 MST 2010 

python /tmp/foo 0.02s user 0.01s system 1% cpu 3.042 total 
guin:/tmp$ 

Correva poco più di 3 secondi, stampati la data 3 volte, e uscirono.

+0

esempio utile, grazie! –

Problemi correlati