首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >调用exit不像预期的那样工作

调用exit不像预期的那样工作
EN

Stack Overflow用户
提问于 2016-05-27 12:07:02
回答 2查看 104关注 0票数 0

我需要在后台运行几个子进程,并在它们之间建立管道数据。当脚本退出时,我想杀死它们中的任何一个,所以我添加了

代码语言:javascript
复制
trap cleanup EXIT

cleanup()
{
    echo "Cleaning up!"
    pkill -TERM -P $$
}

因为我需要在其中一个进程报告错误时做出反应,所以我创建了包装函数。任何以fd结尾的东西都是以前打开的文件描述符,连接到FIFO管道。

代码语言:javascript
复制
run_gui()
{
    "$GAME_BIN" $args <&$gui_infd >&$gui_outfd # redirecting IO to some file descriptors
    if [[ $? == 0 ]]; then
        echo exiting ok
        exit $OK_EXITCODE
    else
        exit $ERROR_EXITCODE
    fi
}

run_ai1(), run_ai2的功能类似。

代码语言:javascript
复制
run_ai1()
{
    "$ai1" <&$ai1_infd >&$ai1_outfd
    if [[ $? == 0 || $? == 1 || $? == 2 ]]; then
        exit $OK_EXITCODE
    else
        exit $ERROR_EXITCODE
    fi
}

run_ai2()
{
    "$ai2" <&$ai2_infd >&$ai2_outfd
    if [[ $? == 0 || $? == 1 || $? == 2 ]]; then
        exit $OK_EXITCODE
    else
        exit $ERROR_EXITCODE
    fi
}

然后运行函数并执行所需的管道操作。

代码语言:javascript
复制
printinit 1 >&$ai1_infd
printinit 2 >&$ai2_infd
run_gui &
run_ai1 &
run_ai2 &
while true; do
    echo "Started the loop"
    while true; do
        read -u $ai1_outfd line || echo "Nothing read"
        echo $line
        if [[ $line ]]; then
            echo "$line" >&$gui_infd
            echo "$line" >&$ai2_infd
            if [[ "$line" == "END_TURN" ]]; then
                break
            fi
        fi
    done
    sleep $turndelay
    while true; do
        read -u $ai2_outfd line || echo "nothing read"
        echo $line
        if [[ $line ]]; then
            echo "$line" >&$gui_infd
            echo "$line" >&$ai1_infd
            if [[ "$line" == "END_TURN" ]]; then
                break
            fi
        fi
    done
    sleep $turndelay
done

$GAME_BIN退出(即GUI被关闭按钮关闭)时,我可以在stdout上看到exiting ok消息,但是根本没有调用cleanup函数。当我在调用cleanup之前添加对exit $OK_EXITCODE的手动调用时,尽管进程被终止了:

代码语言:javascript
复制
./game.sh: line 309:  9193 Terminated              run_gui
./game.sh: line 309:  9194 Terminated              run_ai1
./game.sh: line 309:  9195 Terminated              run_ai2
./game.sh: line 309:  9203 Terminated              sleep $turndelay

循环无论如何都会运行,并且脚本不会像它应该退出的那样退出(exit $OK_EXITCODE)。人工智能脚本很简单:

代码语言:javascript
复制
#!/bin/sh
while true; do
    echo END_TURN
done

我的脚本中任何地方都没有wait调用。我做错了什么?

有趣的是:当我在jobs -p之后立即调用run_ai2 &时,我会列出3个pids。另一方面,当我从cleanup函数调用这个命令时,输出是空的。

此外,为什么sleep $turndelay进程会终止?这不是一个被调用的子进程。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-05-31 16:04:58

当捕获脚本退出时,EXIT陷阱会触发。你的图层剧本不在这里。

trap不是由运行run_*函数的子shell继承的(从后台运行),因此它不会在子shell退出时触发。

你想要的很可能是你手动做的事情(虽然听起来有点不对)。

您希望在cleanup退出时从run_gui调用$GAME函数。就像这样。

代码语言:javascript
复制
run_gui() {
    "$GAME_BIN" $args <&$gui_infd >&$gui_outfd # redirecting IO to some file descriptors
    ret=$?
    cleanup
    exit $ret
}

然后,您只需要确保cleanup获得正确的$$值(在bash中,它甚至在子shell中也是如此,因为子shell中的$$是父进程ID,但是您可能希望在主脚本中为信号设置一个处理程序,并在run_gui终止时给主脚本发送信令)。

票数 1
EN

Stack Overflow用户

发布于 2016-05-27 13:13:01

我猜你得到了一个子进程启动的子进程。这样做:在另一个窗口中做一个ps -ft pts/1或者你的tty是什么。核实一下。

还可以将pkill更改为kill $(jobs -p),并查看这是否有效。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37483161

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档