Как отправить управляющий символ Ctrl-C, или терминальное зависание обмениваются сообщениями к дочернему процессу?

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

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

Как я делаю любой из них? У меня уже есть ведущее устройство имущества fd, и я попробовал что-то вроде этого:

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

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

10
задан Hongli 3 February 2010 в 22:15
поделиться

6 ответов

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

После разветвления вместо немедленного выполнения sudo я выполняю exec () как вспомогательный дочерний процесс, который, в свою очередь, разветвляет и запускает sudo и вызывает на нем 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

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

2
ответ дан 4 December 2019 в 03:16
поделиться

Есть два способа достичь этого:

  • Из дочернего процесса, поймать сигнал SIGCHLD и обработать его, вы можете _выйти(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
ответ дан 4 December 2019 в 03:16
поделиться

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

0
ответ дан 4 December 2019 в 03:16
поделиться

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

ioctl(master, TIOCSTI, &termios.c_cc[VINTR]);
0
ответ дан 4 December 2019 в 03:16
поделиться

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

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

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

0
ответ дан 4 December 2019 в 03:16
поделиться

Я нашел обходной путь для ошибки.

Если удалить APP-файл в build/Debug-iphoneos/перед созданием для устройства, приложение будет установлено без ошибок. И есть простой способ сделать это перед каждым построением.

Убедитесь, что в раскрывающемся меню обзора выбрано «Device». В XCode перейдите в Project > New target... Затем найдите «Shell Script target» в разделе MacOSX/Other Назовите его и добавьте к текущему проекту

Теперь на левой панели навигации в разделе «Цели» разверните вновь созданный объект и дважды щелкните по пункту «Выполнить сценарий». В открывшемся окне замените «# shell script goes here» на «rm -fr build/Debug-iphoneos/* .app» (без кавычек). Теперь откройте основные настройки целевого объекта и в разделе Прямые зависимости добавьте новый целевой объект. Сборка и переход!:)

-121--1130110-

Я думаю, что эта серия из C++ FAQ Lite должна помочь.

Не путайте заголовок «operator overloading». Вы определенно должны прочитать 13.10, 13.11 и 13.12 оттуда.

-121--4716377-

Мне кажется, что если у вас действительно есть пти (если вы не имеете в виду что-то другое под псевдотерминалом), то все, что вам нужно сделать, это отправить 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)

Это развивает процесс под 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 раза и вышел.

4
ответ дан 4 December 2019 в 03:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: