excevp 不接管子进程(C++)

huangapple go评论76阅读模式
英文:

excevp does not take over child process (C++)

问题

以下是翻译好的代码部分:

我正在尝试在我的代码中将Stockfish引擎作为子进程运行。我想使用fork()execvp()来实现这一点。我通过运行以下命令临时将Stockfish可执行文件的位置添加到我的PATH中

export PATH="~/Apps/stockfish_15_linux_x64_avx2:$PATH"


我通过运行`echo $PATH`来确认这已经添加到PATH。我还可以在当前终端会话中的任何目录中运行Stockfish可执行文件,因此这一部分似乎正在工作。我遇到的问题是使用execvp从另一个可执行文件运行Stockfish。

我有以下代码来复现这个问题:

```c
#include <iostream> 
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>

int main(void ) { 
    const char* argv[] = {"stockfish_15_x64_avx2", "d", NULL};
    int pid = fork(); 

    if (pid < 0) { 
        printf("Failed to fork");
    }

    else if (pid == 0){ 
        execvp(argv[0], (char* const*)argv); 
    }

    sleep(1); 

    printf("Finished executing the parent process\n"
    " -- The child won't get here -- you will only see this once.\n");

    return 0;
}

在Stockfish中,d命令显示当前位置的图表。在这种情况下,这将是起始位置。但我得到的输出不是这个图表,而是:

Finished executing the parent process 
 -- The child won't get here -- you will only see this once. 
Finished executing the parent process 
 -- The child won't get here -- you will only see this once.

这告诉我execvp实际上没有接管子进程。当我将参数更改为一个更通用的命令,比如argv[] = {"ls", "-a", NULL}时,代码按预期工作。您知道这里发生了什么吗?


<details>
<summary>英文:</summary>

I am trying to run the stockfish engine as a child process in my code. I want to use fork() and execvp() to do this. I temporarily add the location of the stockfish executable to my PATH by running the command 

``` export PATH=&quot;~/Apps/stockfish_15_linux_x64_avx2:$PATH&quot; ```

And I checked to make sure this is added to PATH by running `echo $PATH`. I can also run the stockfish executable from any directory during my current terminal session, so this part seems to be working. What I am having trouble with is running stockfish from another executable using execvp. 



I have the following code that reproduces the bug. 

#include <iostream>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>

int main(void ) {
const char* argv[] = {"stockfish_15_x64_avx2", "d", NULL};
int pid = fork();

if (pid &lt; 0) { 
    printf(&quot;Failed to fork&quot;);
}

else if (pid == 0){ 
    execvp(argv[0], (char* const*)argv); 
}

sleep( 1 ); 




printf(&quot;Finished executing the parent process \n&quot;
&quot; -- The child won&#39;t get here -- you will only see this once. \n&quot;);

return 0;

}


the `d` command in stockfish displays a diagram of the current position. This would be the start position in this case. But instead of getting this diagram, the output I get is simply 

&lt;!-- language: lang-none --&gt;

Finished executing the parent process
-- The child won't get here -- you will only see this once.
Finished executing the parent process
-- The child won't get here -- you will only see this once.


What this tells me is that execvp is not actually taking over the child process. When I change the arguments to a more generic command like `argv[] = {&quot;ls&quot;, &quot;-a&quot;, NULL}` then the code works as expected. Any idea what is going on here?

</details>


# 答案1
**得分**: 1

我开始使用waitpid进行一些错误处理,当时我有一种直觉,认为可执行文件名中的下划线可能是问题的原因。果然,当我将可执行文件重命名为'stockfish15'时,一切都按预期工作了。

代码现在看起来像这样:

```c
#include <iostream> 
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>

int main(void ) { 
    const char* argv[] = {"stockfish15", "d", NULL};
    pid_t pid = fork(); 
    if (pid == -1) { 
        printf("Failed to fork");
    }
    else if (pid == 0) { 
        execvp(argv[0], (char* const*) argv);
    }

    int status;
    waitpid(pid, &status, 0); 

    if (WIFEXITED(status)) { 
        printf("子进程正常终止\n");
    }

    else {printf("exevp错误\n");}
    
    
    printf("父进程执行完毕\n"
    " -- 子进程不会执行到这里 -- 你只会看到这一次。\n");

    return 0;
}

输出结果为:

Stockfish 15由Stockfish开发者创建(请参阅AUTHORS文件)

 +---+---+---+---+---+---+---+---+
 | r | n | b | q | k | b | n | r | 8
 +---+---+---+---+---+---+---+---+
 | p | p | p | p | p | p | p | p | 7
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 6
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 5
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 4
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 3
 +---+---+---+---+---+---+---+---+
 | P | P | P | P | P | P | P | P | 2
 +---+---+---+---+---+---+---+---+
 | R | N | B | Q | K | B | N | R | 1
 +---+---+---+---+---+---+---+---+
   a   b   c   d   e   f   g   h

Fen: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
密钥:8F8F01D4562F59FB
检查者:
子进程正常终止
父进程执行完毕
 -- 子进程不会执行到这里 -- 你只会看到这一次。

尽管如此,我仍然想知道为什么会发生这种情况的解释。

英文:

So I was starting to use waitpid to do some error handling, when I had a hunch that the underscores in the executable name were somehow the problem. And sure enough, when I renamed the executable to 'stockfish15' everything works as intended.

The code now looks like this

#include &lt;iostream&gt; 
#include &lt;sys/types.h&gt;
#include &lt;sys/wait.h&gt;
#include &lt;stdio.h&gt;
#include &lt;unistd.h&gt;

int main(void ) { 
    const char* argv[] = {&quot;stockfish15&quot;, &quot;d&quot;, NULL};
    pid_t pid = fork(); 
    if (pid == -1) { 
        printf(&quot;Failed to fork&quot;);
    }
    else if (pid == 0) { 
        execvp(argv[0], (char* const*) argv);
    }

    int status;
    waitpid(pid, &amp;status, 0); 

    if (WIFEXITED(status)) { 
        printf(&quot;child terminated normally\n&quot;);
    }

    else {printf(&quot;exevp error\n&quot;);}
    
    
    printf(&quot;Finished executing the parent process \n&quot;
    &quot; -- The child won&#39;t get here -- you will only see this once. \n&quot;);

    return 0;
}

and the output is
<!-- language: lang-none -->

Stockfish 15 by the Stockfish developers (see AUTHORS file)

 +---+---+---+---+---+---+---+---+
 | r | n | b | q | k | b | n | r | 8
 +---+---+---+---+---+---+---+---+
 | p | p | p | p | p | p | p | p | 7
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 6
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 5
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 4
 +---+---+---+---+---+---+---+---+
 |   |   |   |   |   |   |   |   | 3
 +---+---+---+---+---+---+---+---+
 | P | P | P | P | P | P | P | P | 2
 +---+---+---+---+---+---+---+---+
 | R | N | B | Q | K | B | N | R | 1
 +---+---+---+---+---+---+---+---+
   a   b   c   d   e   f   g   h

Fen: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
Key: 8F8F01D4562F59FB
Checkers: 
child terminated normally
Finished executing the parent process 
 -- The child won&#39;t get here -- you will only see this once. 

Still, I'd like to know the explanation for why this is happening.

huangapple
  • 本文由 发表于 2023年3月4日 01:10:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75630015.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定