<commit_before>#if defined(__unix__) || defined(__APPLE__)

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <signal.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

#include "Tools.h"
#include "Types.h"

void StartBotProcess(const BotConfig &Agent, const std::string &CommandLine, unsigned long *ProcessId)
{
    pid_t pID = fork();

    if (pID < 0)
    {
        std::cerr << Agent.BotName + ": Can't fork the bot process, error: " +
            strerror(errno) << std::endl;
        return;
    }

    if (pID == 0) // child
    {
        close(STDIN_FILENO);
        close(STDOUT_FILENO);

        // FIXME (alkurbatov): Redirect stderr to a file like ToolsWindows do.
        //close(STDERR_FILENO);

        int ret = chdir(Agent.RootPath.c_str());
        if (ret < 0) {
            std::cerr << Agent.BotName +
                ": Can't change working directory to " + Agent.RootPath +
                ", error: " + strerror(errno) << std::endl;
            exit(errno);
        }

        std::vector<char*> unix_cmd;
        std::istringstream stream(CommandLine);
        std::istream_iterator<std::string> begin(stream), end;
        std::vector<std::string> tokens(begin, end);
        for (const auto& i : tokens)
            unix_cmd.push_back(const_cast<char*>(i.c_str()));

        // FIXME (alkurbatov): Unfortunately, the cmdline uses relative path.
        // This hack is needed because we have to change the working directory
        // before calling to exec.
        if (Agent.Type == BinaryCpp)
            unix_cmd[0] = const_cast<char*>(Agent.FileName.c_str());

        unix_cmd.push_back(NULL);

        ret = execv(unix_cmd.front(), &unix_cmd.front());
        if (ret < 0)
        {
            std::cerr << Agent.BotName + ": Failed to execute '" + CommandLine +
                "', error: " + strerror(errno) << std::endl;
            exit(errno);
        }

        exit(0);
    }

    // parent
    *ProcessId = pID;

    int exit_status = 0;
    int ret = waitpid(pID, &exit_status, 0);
    if (ret < 0) {
        std::cerr << Agent.BotName +
            ": Can't wait for the child process, error:" +
            strerror(errno) << std::endl;
    }
}

void SleepFor(int seconds)
{
    sleep(seconds);
}

void KillSc2Process(unsigned long pid)
{
    kill(pid, SIGKILL);
}

bool MoveReplayFile(const char* lpExistingFileName, const  char* lpNewFileName)
{
	// todo
	throw "MoveFile is not implemented for linux yet.";
}

#endif<commit_msg>KillSc2Process: Verify that SIGKILL was sent<commit_after>#if defined(__unix__) || defined(__APPLE__)

#include <iostream>
#include <sstream>
#include <string>
#include <vector>

#include <signal.h>
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>

#include "Tools.h"
#include "Types.h"

void StartBotProcess(const BotConfig &Agent, const std::string &CommandLine, unsigned long *ProcessId)
{
    pid_t pID = fork();

    if (pID < 0)
    {
        std::cerr << Agent.BotName + ": Can't fork the bot process, error: " +
            strerror(errno) << std::endl;
        return;
    }

    if (pID == 0) // child
    {
        close(STDIN_FILENO);
        close(STDOUT_FILENO);

        // FIXME (alkurbatov): Redirect stderr to a file like ToolsWindows do.
        //close(STDERR_FILENO);

        int ret = chdir(Agent.RootPath.c_str());
        if (ret < 0) {
            std::cerr << Agent.BotName +
                ": Can't change working directory to " + Agent.RootPath +
                ", error: " + strerror(errno) << std::endl;
            exit(errno);
        }

        std::vector<char*> unix_cmd;
        std::istringstream stream(CommandLine);
        std::istream_iterator<std::string> begin(stream), end;
        std::vector<std::string> tokens(begin, end);
        for (const auto& i : tokens)
            unix_cmd.push_back(const_cast<char*>(i.c_str()));

        // FIXME (alkurbatov): Unfortunately, the cmdline uses relative path.
        // This hack is needed because we have to change the working directory
        // before calling to exec.
        if (Agent.Type == BinaryCpp)
            unix_cmd[0] = const_cast<char*>(Agent.FileName.c_str());

        unix_cmd.push_back(NULL);

        ret = execv(unix_cmd.front(), &unix_cmd.front());
        if (ret < 0)
        {
            std::cerr << Agent.BotName + ": Failed to execute '" + CommandLine +
                "', error: " + strerror(errno) << std::endl;
            exit(errno);
        }

        exit(0);
    }

    // parent
    *ProcessId = pID;

    int exit_status = 0;
    int ret = waitpid(pID, &exit_status, 0);
    if (ret < 0) {
        std::cerr << Agent.BotName +
            ": Can't wait for the child process, error:" +
            strerror(errno) << std::endl;
    }
}

void SleepFor(int seconds)
{
    sleep(seconds);
}

void KillSc2Process(unsigned long pid)
{
    int ret = kill(pid, SIGKILL);
    if (ret < 0)
    {
        std::cerr << std::string("Failed to send SIGKILL, error:") +
            strerror(errno) << std::endl;
    }
}

bool MoveReplayFile(const char* lpExistingFileName, const  char* lpNewFileName)
{
	// todo
	throw "MoveFile is not implemented for linux yet.";
}

#endif
{'fraction_non_alphanumeric': 0.1393082361933881, 'fraction_numerical': 0.004204089432447927, 'mean_word_length': 2.3594351732991012, 'pattern_counts': {'":': 8, '<': 74, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1761577', 'n_tokens_mistral': 1733, 'n_tokens_neox': 1674, 'n_words': 417}