即使要用SIGINT停止第91行(gdb)上的命令(通过Ctrl + C),我也要使第92行(killall)上的命令执行:
88 debug:
89 make all
90 make flash
91 -$(GDB) $(PROJ_NAME).elf $(GDBCOMMANDS)
92 killall openocd
但是,即使make打印有关忽略该中断的信息,但此后它仍然不会运行killall:
make: [Makefile:91: debug] Interrupt (ignored)
在不使用SIGINT的情况下退出GDB时,所有工作都按预期进行-执行killall。
在上述情况下,为什么make不尝试执行killall? 我该如何运作?
您可以使用此Makefile自己测试问题(如果退出前在手动窗口中按CTRL + C,则不会执行回显,但如果工作正常,只需按“ q”退出即可):
all:
-man man
echo 'It worked!'
答案 0 :(得分:0)
问题在于,^ C也被make捕获(当您运行^ C时,终端进程组中的所有进程都接收到该信号),make退出(清理后),因此它从不尝试运行任何更多命令,就像在制作过程中输入^ C一样。
避免这种情况的唯一方法是确保make完全不接收SIGINT,并且这样做的唯一方法是更改流程组。我不确定是否有任何方便的实用程序可以帮您实现这一目标。
我的建议是不要尝试从制造配方内部调用调试器或其他交互式程序。它不是为此设计的。除了上述问题之外,您还会发现,如果尝试在启用并行构建的情况下运行,则由于只有一个进程可以从终端获取标准输入,因此将随机选择一个进程来获取“真实”标准输入,而其他将关闭其stdin或从/ dev / null或其他内容读取。
相反,为什么不创建一个Shell脚本来进行调试,该脚本将运行您想要的make命令,然后调用gdb。此shell脚本可以使用trap
来捕获SIGINT并忽略它,以确保它始终运行清除。
答案 1 :(得分:0)
可接受的答案很好地说明了make的问题,但是要使解决方案仅在make中起作用,可以使用.ONESHELL
来完成trap
。
man
似乎独自忽略了SIGINT
,因此,这并不是最好的测试案例debug: all flash
(但请记住有关并行性的警告).ONESHELL
,明智的做法是也选择.SHELLFLAGS
,否则您的食谱将不会像以前那样使用。编辑:正如评论中指出的那样,不要期望在此之后会建立其他目标。
.ONESHELL:
# The flag -e mimics the traditional behaviour of exiting as soon as any command fails
.SHELLFLAGS := -e -c
debug: all flash
trap 'true' INT
$(GDB) $(PROJ_NAME).elf $(GDBCOMMANDS) || error=$$?
killall openocd # All of them?
exit $${error}