<commit_before>#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>

#include "rtl_exec.h"

namespace rtl {

Number process$call(const std::string &command, std::string *stdout, std::string *stderr)
{
    int pout[2];
    int perr[2];
    if (pipe(pout) != 0) {
        throw RtlException(Exception_os$SystemException, std::to_string(errno));
    }
    if (pipe(perr) != 0) {
        throw RtlException(Exception_os$SystemException, std::to_string(errno));
    }
    pid_t child = fork();
    if (child < 0) {
        throw RtlException(Exception_os$SystemException, std::to_string(errno));
    }
    if (child == 0) {
        close(pout[0]);
        close(perr[0]);
        dup2(pout[1], 1);
        close(pout[1]);
        dup2(perr[1], 2);
        close(perr[1]);
        for (int i = 3; i < 1024; i++) { // TODO: get runtime system limit
            close(i);
        }
        execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL);
        _exit(127);
    }
    close(pout[1]);
    close(perr[1]);
    for (;;) {
        fd_set fds;
        FD_ZERO(&fds);
        int nfds = 0;
        if (pout[0] >= 0) {
            FD_SET(pout[0], &fds);
            nfds = std::max(nfds, pout[0] + 1);
        }
        if (perr[0] >= 0) {
            FD_SET(perr[0], &fds);
            nfds = std::max(nfds, perr[0] + 1);
        }
        if (nfds == 0) {
            break;
        }
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        int r = select(nfds, &fds, NULL, NULL, &tv);
        if (r < 0) {
            throw RtlException(Exception_os$SystemException, std::to_string(errno));
        }
        if (FD_ISSET(pout[0], &fds)) {
            char buf[1024];
            ssize_t n = read(pout[0], buf, sizeof(buf));
            if (n > 0) {
                stdout->append(std::string(buf, n));
            } else {
                close(pout[0]);
                pout[0] = -1;
            }
        }
        if (FD_ISSET(perr[0], &fds)) {
            char buf[1024];<commit_msg>Fix crash problem with posix process.call<commit_after>#include <errno.h>
#include <sys/wait.h>
#include <unistd.h>

#include "rtl_exec.h"

namespace rtl {

Number process$call(const std::string &command, std::string *stdout, std::string *stderr)
{
    int pout[2];
    int perr[2];
    if (pipe(pout) != 0) {
        throw RtlException(Exception_os$SystemException, std::to_string(errno));
    }
    if (pipe(perr) != 0) {
        throw RtlException(Exception_os$SystemException, std::to_string(errno));
    }
    pid_t child = fork();
    if (child < 0) {
        throw RtlException(Exception_os$SystemException, std::to_string(errno));
    }
    if (child == 0) {
        close(pout[0]);
        close(perr[0]);
        dup2(pout[1], 1);
        close(pout[1]);
        dup2(perr[1], 2);
        close(perr[1]);
        for (int i = 3; i < 1024; i++) { // TODO: get runtime system limit
            close(i);
        }
        execl("/bin/sh", "/bin/sh", "-c", command.c_str(), NULL);
        _exit(127);
    }
    close(pout[1]);
    close(perr[1]);
    for (;;) {
        fd_set fds;
        FD_ZERO(&fds);
        int nfds = 0;
        if (pout[0] >= 0) {
            FD_SET(pout[0], &fds);
            nfds = std::max(nfds, pout[0] + 1);
        }
        if (perr[0] >= 0) {
            FD_SET(perr[0], &fds);
            nfds = std::max(nfds, perr[0] + 1);
        }
        if (nfds == 0) {
            break;
        }
        struct timeval tv;
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        int r = select(nfds, &fds, NULL, NULL, &tv);
        if (r < 0) {
            throw RtlException(Exception_os$SystemException, std::to_string(errno));
        }
        if (pout[0] >= 0 && FD_ISSET(pout[0], &fds)) {
            char buf[1024];
            ssize_t n = read(pout[0], buf, sizeof(buf));
            if (n > 0) {
                stdout->append(std::string(buf, n));
            } else {
                close(pout[0]);
                pout[0] = -1;
            }
        }
        if (perr[0] >= 0 && FD_ISSET(perr[0], &fds)) {
            char buf[1024];
{'fraction_non_alphanumeric': 0.17097560975609757, 'fraction_numerical': 0.02829268292682927, 'mean_word_length': 1.7916950306330837, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 19, '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': '2843130', 'n_tokens_mistral': 1571, 'n_tokens_neox': 1488, 'n_words': 304}