问题描述
有人可以从低层次解释这里发生了什么吗?为什么从Python3,Rake,Ruby或Make中将shell(bash,ksh)作为子子进程启动,会导致终端的行为就像父进程没有收到ctrl-c生成的SIGINT一样?当子进程不是shell时,父级当然会中断,那么到底发生了什么呢?我看到孩子和父母在整个执行过程中都属于同一进程组。
孩子如何使父母对SIGINT免疫?如果通过频道重新路由或其他一些花哨的技巧来完成此操作,请举例说明如何完成此操作。我想修复在我看到的具有CLI的EDA工具之间行为不一致的问题;有些行为像Bash在子过程中一样,其他行为则留为孤儿。
测试代码:
该代码将首先启动bash作为子进程,尽管被Python3封装了,但不能被ctrl-c中断。您将需要exit
返回到父级。然后,代码将启动具有中断处理程序的child.py。当您在子对象中按ctrl-c时,您将看到parent.py引发和child.py都同时中断,而child.py处于孤岛状态,而其SIGINT处理程序却喷向了stdout;退出状态是父母的状态;孩子的状态不见了。
parent.py:
#!/usr/bin/env python3
import os,sys
import subprocess
import signal
import time
PID = os.getpid()
PGID = os.getpgid(PID)
PROC_LABEL = f'PARENT: pid={PID},pgid={PGID}'
print(f"{PROC_LABEL}: spawning bash...")
proc = subprocess.Popen(['bash'])
ret = proc.wait()
print(f"{PROC_LABEL}: child exit status:",proc.returncode)
print(f"{PROC_LABEL}: spawning ./child.py...")
proc = subprocess.Popen(['./child.py'])
proc.wait()
print(f"{PROC_LABEL}: child exit status:",proc.returncode)
sys.exit(0)
child.py
#!/usr/bin/env python3
import os,sys
import signal
import time
PID = os.getpid()
PGID = os.getpgid(PID)
PROC_LABEL = f"CHILD : pid={PID}; pgid={PGID}"
def intr_handler(sig,frame):
print(f'\n{PROC_LABEL}: Trapped: {signal.Signals(sig).name}')
for idx in range(3,-1):
print(f"{PROC_LABEL}: sleeping for {idx} seconds")
time.sleep(1)
print(f"{PROC_LABEL}: bye")
sys.exit(100)
signal.signal(signal.SIGINT,intr_handler)
ret = input(f"{PROC_LABEL}: type something: ")
print("input:",ret)
sys.exit(0)
执行:
$ ./parent.py
PARENT: pid=3121412,pgid=3121412: spawning bash...
bash> ^C
bash> exit 0
exit
PARENT: pid=3121412,pgid=3121412: child exit status: 0
PARENT: pid=3121412,pgid=3121412: spawning ./child.py...
CHILD : pid=3121728; pgid=3121412: type something: ^C
CHILD : pid=3121728; pgid=3121412: Trapped: SIGINT
CHILD : pid=3121728; pgid=3121412: sleeping for 3 seconds
Traceback (most recent call last):
File "./parent.py",line 18,in <module>
proc.wait()
File "/m/tools/lang/python/pyenv/versions/3.7.6/lib/python3.7/subprocess.py",line 1019,in wait
return self._wait(timeout=timeout)
File "/m/tools/lang/python/pyenv/versions/3.7.6/lib/python3.7/subprocess.py",line 1653,in _wait
(pid,sts) = self._try_wait(0)
File "/m/tools/lang/python/pyenv/versions/3.7.6/lib/python3.7/subprocess.py",line 1611,in _try_wait
(pid,sts) = os.waitpid(self.pid,wait_flags)
KeyboardInterrupt
$ CHILD : pid=3121728; pgid=3121412: sleeping for 2 seconds
CHILD : pid=3121728; pgid=3121412: sleeping for 1 seconds
CHILD : pid=3121728; pgid=3121412: bye
echo $?
1
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)