如何将Ctrl-C控制字符或终端挂断消息发送到子进程?

时间:2010-02-03 22:15:23

标签: c posix pty

我有一个在伪终端中运行的子进程。父进程不以root身份运行,但子进程通过su或sudo运行。因此,无法向子进程发送信号以强制它退出。我想通过以下方法之一强制退出:

  • 模拟Ctrl-C。
  • 模拟终端挂断。

我如何做其中任何一项?我已经有了一个pty master fd,我尝试过这样的事情:

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

但它没有做任何事情。

6 个答案:

答案 0 :(得分:4)

在我看来,如果你真的有一个pty(除非你的意思是伪终端的其他东西),你所要做的就是向该FD发送一个Control-C。作为这方面的证据,我在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秒并发送一个control-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次,然后退出。

答案 1 :(得分:2)

我最终选择了以下解决方案:

在分叉之后,我不再立即执行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 :(得分: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)

有两个想到的......抱歉,如果没有对你的进一步帮助,

希望这有帮助, 最好的祝福, 汤姆。

答案 3 :(得分:0)

关闭主设备应该向从设备的控制进程组发出挂断信号。

答案 4 :(得分:0)

我认为您需要使用ioctl来插入中断字符而不是write。不幸的是,这种机制似乎并不便携。对于Linux,它看起来可能有用:

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

答案 5 :(得分:0)

我要检查的第一件事是你是否需要将它作为奴隶侧的控制终端。事实证明这是more complex,而不是我记得,ptys默认情况下可能无法控制。这个链接适用于Linux,其他系统应该根据他们的SysV和BSD-ness做一个或另一个,但看起来TIOCSCTTY是一个不错的选择。

其次,我会检查你是否在你的termios中设置了ISIG;如果没有,VINTR和VQUIT将无法正常工作。

当然,如果另一端正在捕捉SIGINT和SIGQUIT,那么你还会遇到其他问题。