2010-02-03 3 views
10

У меня есть дочерний процесс, который работает в псевдотерминале. Родительский процесс не запускается с правами root, но дочерний процесс выполняется через su или sudo. Из-за этого невозможно отправить сигнал дочернему процессу, чтобы заставить его выйти. Я хочу заставить его выйти одним из следующих способов:Как отправить управляющий символ Ctrl-C или сообщение о зависании терминала дочернему процессу?

  • эмулировать Ctrl-C.
  • Эмуляция терминала зависания.

Как мне это сделать? У меня уже есть мастер псевдотерминал FD, и я пытался что-то вроде этого:

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

, но ничего не делает.

+0

Я не знаю, будет ли это работать с вашей программой/pty, но что я делаю с тех пор, как я запускаю bash, а bash берет^C как SIGINT по умолчанию [я думаю?] Делает char, который содержит hex code: (0x03 для^C), а затем записать его в мой pty с помощью: write (m_nMaster, & ctrlC, sizeof (ctrlC)); – 2010-02-08 17:24:28

ответ

2

В конце концов я пошел следующий раствор:

После разветвления, вместо того, чтобы немедленно exec'ing Sudo, я EXEC дочерний процесс вспомогательного() вместо этого, который в своей очереди вилка и EXECS Суда и вызовах waitpid на него. Таким образом, иерархия процесса выглядит следующим образом:

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 

Убивая процесс вспомогательного, то псевдотерминал не имеет приоритетный процесса больше. Это заставит ОС отправлять SIGHUP во всю группу процессов переднего плана, независимо от пользователя, поэтому sudo также SIGHUP'ed.

0

Существует два пути достижения этой цели:

  • дочернего процесса, ловушки сигнал SIGCHLD и обработать его, вы можете _Exit (0), чтобы закончить процесс ребенка
  • Там это программа под названием ptree , Вы могли бы обмануть это, делая это таким образом ... в псевдокоде:
 
obtain the parent's pid. 
using _popen("ptree %d", parent_pid) 
for each entry of child process 
system ("kill -1 %d", child_process_pid) 

Там два, что приходит на ум ... жаль, если его не далее помочь вам,

Надежда это помогает, С уважением, Том.

+0

Он не может напрямую сигнализировать ребенку, потому что он работает под другим эффективным uid. – caf

+0

@caf: hmmm .... можете ли вы ответить на это? представьте, если дочерний процесс запущен на псевдотерминале, возьмите это под Linux-примером ... если двоичный файл должен был быть помещен в псевдотерминал say/dev/pty4, где находится дочерний процесс, то это вызовет оконечная развязка терминала? т. е. cat binary_file>/dev/pty4 – t0mm13b

+0

Нет, зачем? Он просто доставляет эти байты на основную сторону пары псевдотерминалов. – caf

0

Закрытие главного устройства должно сигнализировать о зависании с группой управления процессом ведомого.

0

Я думаю, вам нужно использовать ioctl, чтобы вставить символ прерывания вместо write. К сожалению, механизм для этого не кажется переносимым. Для Linux это выглядит это может работать:

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

Я получаю сообщение об ошибке «отказ в доступе»/«операция не разрешена». Если я запускаю процесс как root, тогда я получаю «время ожидания операции». – Hongli

0

Первое, что я бы проверить, если вам нужно сделать контрольный терминал на подчиненном стороне. Оказывается, это more complex, чем я помню, поскольку ptys, возможно, не стал контролировать по умолчанию. Эта ссылка для Linux, другие системы должны делать то или другое в зависимости от их SysV и BSD-ness, но похоже, что TIOCSCTTY - хорошая ставка, чтобы попробовать.

Во-вторых, я бы проверял, устанавливаете ли вы ISIG в своих терминах; если нет, VINTR и VQUIT не будут работать.

Конечно, если другой конец ловит SIGINT и SIGQUIT, у вас появятся другие проблемы.

4

Мне кажется, что если у вас действительно есть pty (если вы не имеете в виду что-то еще псевдотерминалом), все, что вам нужно сделать, это отправить Control-C в этот FD. В качестве доказательства этого, я представить следующий код в Python (но довольно близко к C требуется, чтобы сделать это):

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) 

This порождает процесс под Pty, которая проходит бесконечный цикл печати на дату. Затем родитель ждет 3 секунды и отправляет элемент управления-C.

Это приводит следующий вывод:

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$ 

Он побежал чуть более 3 секунд, распечатывается дата истечения 3 раза, и вышел.

+0

полезный пример, спасибо! –

Смежные вопросы