Search code examples
c++linuxexecparent-childchild-process

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


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="~/Apps/stockfish_15_linux_x64_avx2:$PATH"

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 < 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;
}

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

 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[] = {"ls", "-a", NULL} then the code works as expected. Any idea what is going on here?


Solution

  • 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 <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("child terminated normally\n");
        }
    
        else {printf("exevp error\n");}
        
        
        printf("Finished executing the parent process \n"
        " -- The child won't get here -- you will only see this once. \n");
    
        return 0;
    }
    

    and the output is

    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't get here -- you will only see this once. 
    

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