C ruby成功时IRB无法运行ruby gem函数

C ruby成功时IRB无法运行ruby gem函数,c,ruby,malloc,C,Ruby,Malloc,我最近制作了以下ruby gem(称为sse): #包括 #包括 #包括 #包括 #包括 #包括 #包括 /* *模块手柄 */ 静态值sse_模块; /* *此模块的所有例外情况 */ 静态值sse_FileNotFoundError; 静态值sse_ForkFailureError; 静态值sse_管道故障错误; 静态值sse_WriteFailureError; 静态值sse_ReadFailureError; 静态值sse_WaitpidFailureError; 静态值sse_Time

我最近制作了以下ruby gem(称为sse):

#包括
#包括
#包括
#包括
#包括
#包括
#包括
/*
*模块手柄
*/
静态值sse_模块;
/*
*此模块的所有例外情况
*/
静态值sse_FileNotFoundError;
静态值sse_ForkFailureError;
静态值sse_管道故障错误;
静态值sse_WriteFailureError;
静态值sse_ReadFailureError;
静态值sse_WaitpidFailureError;
静态值sse_TimeoutError;
/*
*一般公用事业
*/
字符**拆分(字符*str,字符*sep){
char*arg=strtok(str,sep);
大小参数列表大小=1;
char**arg_list=malloc(sizeof(char*));
arg_list[0]=malloc(strlen(arg));
strncpy(arg_list[0],arg,strlen(arg));
while((arg=strtok(NULL,sep))!=NULL){
arg_list=realloc(arg_list,(sizeof(char*))*(arg_list_size+1));
arg_list[arg_list_size]=malloc(strlen(arg));
strncpy(arg_list[arg_list_size],arg,strlen(arg));
++参数列表大小;
}
arg_list=realloc(arg_list,(sizeof(char*))*(arg_list_size));
arg_list[arg_list_size]=malloc(sizeof(char*));
arg_list[arg_list_size]=(char*)空;
返回参数列表;
}
/*
*Ruby类和函数
*/
值rb_执行(值self、值rb_stdin、值rb_超时、值rb_命令){
int stdin_结束[2];
int stdout_结束[2];
int stderr_结束[2];
如果(管道(标准端)=-1(标准端)=-1(标准端)=-1(标准端)=-1(标准端)=-1){
rb_raise(sse_管道故障错误,“%s:%d(%d)管道:%s\n”、_文件、_行、错误号、strerror(错误号));
}
char**command_list=split(StringValueCStr(rb_命令),(char*)“”);
char*stdin_buf=StringValueCStr(rb_stdin);
pid_t pid=fork();
如果(pid>0){
尺寸标准尺寸=0;
尺寸标准尺寸=0;
尺寸标准尺寸最大值=1;
尺寸标准最大值=1;
char*stdout_buf=malloc(1);
char*stderr_buf=malloc(1);
标准值[0]='\0';
stderr_buf[0]='\0';
时间\u t开始=时间(空);
time\u t timeout=NUM2INT(rb\u timeout);
int sent_stdin=0;
关闭(标准输入端[0]);
关闭(stdout_结束[1]);
关闭(标准端[1]);
while(difftime(time(NULL),start)<超时){
int status=waitpid(pid,NULL,WNOHANG);
如果(状态==-1){
rb_raise(sse_WaitpidFailureError,“%s:%d(%d)waitpid:%s\n”、_文件、_行、错误号、strerror(错误号));
}否则如果(状态==0){
fd_集写入_集;
fd_集读取_集;
struct timeval select_timeout={0,0};
int maxfd=(标准端[1]>标准端[0]?(标准端[1]>标准端[0]?标准端[1]:标准端[0]:(标准端[0]>标准端[0]?标准端[0]:标准端[0]);
FD_零(写入集和写入集);
FD_零(读取集和读取集);
如果(发送的标准数据==0){
FD_集(stdin_结束[1],&write_集);
}
FD_集(标准输出端[0],&读取_集);
FD_集(stderr_结束[0],&read_集);
选择(maxfd+1、&read\u set、&write\u set、NULL、&select\u timeout);
if(FD_-ISSET(stdin_结束[1],&write_-set)){
发送的标准数据=1;
if(写入(标准输入端[1],标准输入端[1],标准输入端[1],标准输入端[1])=-1){
rb_raise(sse_WriteFailureError,“%s:%d(%d)write:%s\n”、_文件、_行、errno、strerror(errno));
}
关闭(标准端[1]);
}
if(FD_ISSET(stdout_结束[0],&read_set)){
char tmp_buf[251];
ssize_t bytes_read=read(标准输出结束[0],tmp_buf,250);
如果(字节数_读取==-1){
rb_raise(sse_ReadFailureError,“%s:%d(%d)读取:%s\n”、_文件、_行、错误号、strerror(错误号));
}
tmp_buf[bytes_read]='\0';
而((标准大小+字节读取+1)>=标准大小最大值){
stdout_buf_max*=2;
stdout_buf=realloc(stdout_buf,stdout_buf_max);
}
strncpy(stdout\u buf、tmp\u buf、字节读取);
stdout_buf_size+=读取的字节数;
标准尺寸[标准尺寸]='\0';
}
if(FD_ISSET(stderr_结束[0],&read_set)){
char tmp_buf[251];
ssize_t bytes_read=read(stderr_ends[0],tmp_buf,250);
如果(字节数_读取==-1){
rb_raise(sse_ReadFailureError,“%s:%d(%d)读取:%s\n”、_文件、_行、错误号、strerror(错误号));
}
tmp_buf[bytes_read]='\0';
而((标准大小+字节读取+1)>=标准大小最大值){
stderr_buf_max*=2;
stderr_buf=realloc(stderr_buf,stderr_buf_max);
}
strncpy(stderr_buf、tmp_buf、字节读取);
stderr_buf_size+=读取的字节数;
标准尺寸[标准尺寸]='\0';
}
}否则{
关闭(stdout_结束[0]);
关闭(标准端[1]);
值结果=rb_ary_new2(3);
rb_ary_存储(result,0,INT2NUM(difftime,time(NULL),start));
rb_ary_存储(结果,1,rb_stru_new_cstr(stdout_buf));
rb_ary_存储(结果,2,rb_stru_new_cstr(stderr_buf));
返回结果;
}
}
kill(SIGINT,pid);
rb_raise(sse_TimeoutError,“过程花费的时间太长而无法完成。\n”);
}否则如果(pid==0){
dup2(标准数据单元结束[0],标准数据单元文件号);
dup2(标准输出端[1],标准输出文件号);
dup2(stderr_结束[1],stderr_文件号);
关闭(标准端[1
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <signal.h>

/*
 * Module handle
*/

static VALUE sse_module;

/*
 * All exceptions for this module
*/

static VALUE sse_FileNotFoundError;
static VALUE sse_ForkFailureError;
static VALUE sse_PipeFailureError;
static VALUE sse_WriteFailureError;
static VALUE sse_ReadFailureError;
static VALUE sse_WaitpidFailureError;
static VALUE sse_TimeoutError;

/*
 * General utilities
*/

char **split(char *str, char *sep) {
    char *arg = strtok(str, sep);
    size_t arg_list_size = 1;
    char **arg_list = malloc(sizeof(char*));

    arg_list[0] = malloc(strlen(arg));
    strncpy(arg_list[0], arg, strlen(arg));

    while((arg = strtok(NULL, sep)) != NULL) {
        arg_list = realloc(arg_list, (sizeof(char*))*(arg_list_size+1));
        arg_list[arg_list_size] = malloc(strlen(arg));
        strncpy(arg_list[arg_list_size], arg, strlen(arg));
        ++arg_list_size;
    }

    arg_list = realloc(arg_list, (sizeof(char*))*(arg_list_size));
    arg_list[arg_list_size] = malloc(sizeof(char*));
    arg_list[arg_list_size] = (char*)NULL;

    return arg_list;
}

/*
 * Ruby classes and functions
*/

VALUE rb_execute_sh(VALUE self, VALUE rb_stdin, VALUE rb_timeout, VALUE rb_command) {
    int stdin_ends[2];
    int stdout_ends[2];
    int stderr_ends[2];

    if(pipe(stdin_ends) == -1 || pipe(stdout_ends) == -1 || pipe(stderr_ends) == -1) {
        rb_raise(sse_PipeFailureError, "%s:%d (%d) pipe: %s\n", __FILE__, __LINE__, errno, strerror(errno));
    }

    char **command_list = split(StringValueCStr(rb_command), (char*)" ");
    char *stdin_buf = StringValueCStr(rb_stdin);
    pid_t pid = fork();

    if(pid > 0) {
        size_t stdout_buf_size = 0;
        size_t stderr_buf_size = 0;
        size_t stdout_buf_max = 1;
        size_t stderr_buf_max = 1;
        char *stdout_buf = malloc(1);
        char *stderr_buf = malloc(1);

        stdout_buf[0] = '\0';
        stderr_buf[0] = '\0';

        time_t start = time(NULL);
        time_t timeout = NUM2INT(rb_timeout);
        int sent_stdin = 0;

        close(stdin_ends[0]);
        close(stdout_ends[1]);
        close(stderr_ends[1]);

        while(difftime(time(NULL), start) < timeout) {
            int status = waitpid(pid, NULL, WNOHANG);

            if(status == -1) {
                rb_raise(sse_WaitpidFailureError, "%s:%d (%d) waitpid: %s\n", __FILE__, __LINE__, errno, strerror(errno));
            } else if(status == 0) {
                fd_set write_set;
                fd_set read_set;
                struct timeval select_timeout = { 0, 0 };
                int maxfd = (stdin_ends[1] > stdout_ends[0] ? (stdin_ends[1] > stderr_ends[0] ? stdin_ends[1] : stderr_ends[0]) : (stdout_ends[0] > stderr_ends[0] ? stdout_ends[0] : stderr_ends[0]));

                FD_ZERO(&write_set);
                FD_ZERO(&read_set);

                if(sent_stdin == 0) {
                    FD_SET(stdin_ends[1], &write_set);
                }

                FD_SET(stdout_ends[0], &read_set);
                FD_SET(stderr_ends[0], &read_set);

                select(maxfd+1, &read_set, &write_set, NULL, &select_timeout);

                if(FD_ISSET(stdin_ends[1], &write_set)) {
                    sent_stdin = 1;

                    if(write(stdin_ends[1], stdin_buf, strlen(stdin_buf)) == -1) {
                        rb_raise(sse_WriteFailureError, "%s:%d (%d) write: %s\n", __FILE__, __LINE__, errno, strerror(errno));
                    }

                    close(stdin_ends[1]);
                }

                if(FD_ISSET(stdout_ends[0], &read_set)) {
                    char tmp_buf[251];
                    ssize_t bytes_read = read(stdout_ends[0], tmp_buf, 250);

                    if(bytes_read == -1) {
                        rb_raise(sse_ReadFailureError, "%s:%d (%d) read: %s\n", __FILE__, __LINE__, errno, strerror(errno));
                    }

                    tmp_buf[bytes_read] = '\0';

                    while((stdout_buf_size + bytes_read+1) >= stdout_buf_max) {
                        stdout_buf_max *= 2;
                        stdout_buf = realloc(stdout_buf, stdout_buf_max);
                    }

                    strncpy(stdout_buf, tmp_buf, bytes_read);
                    stdout_buf_size += bytes_read;
                    stdout_buf[stdout_buf_size] = '\0';
                }

                if(FD_ISSET(stderr_ends[0], &read_set)) {
                    char tmp_buf[251];
                    ssize_t bytes_read = read(stderr_ends[0], tmp_buf, 250);

                    if(bytes_read == -1) {
                        rb_raise(sse_ReadFailureError, "%s:%d (%d) read: %s\n", __FILE__, __LINE__, errno, strerror(errno));
                    }

                    tmp_buf[bytes_read] = '\0';

                    while((stderr_buf_size + bytes_read+1) >= stderr_buf_max) {
                        stderr_buf_max *= 2;
                        stderr_buf = realloc(stderr_buf, stderr_buf_max);
                    }

                    strncpy(stderr_buf, tmp_buf, bytes_read);
                    stderr_buf_size += bytes_read;
                    stderr_buf[stderr_buf_size] = '\0';
                }
            } else {
                close(stdout_ends[0]);
                close(stderr_ends[1]);
                VALUE result = rb_ary_new2(3);
                rb_ary_store(result, 0, INT2NUM(difftime(time(NULL), start)));
                rb_ary_store(result, 1, rb_str_new_cstr(stdout_buf));
                rb_ary_store(result, 2, rb_str_new_cstr(stderr_buf));
                return result;
            }
        }

        kill(SIGINT, pid);
        rb_raise(sse_TimeoutError, "Proccess took too long to finish.\n");
    } else if(pid == 0) {
        dup2(stdin_ends[0], STDIN_FILENO);
        dup2(stdout_ends[1], STDOUT_FILENO);
        dup2(stderr_ends[1], STDERR_FILENO);
        close(stdin_ends[1]);
        close(stdout_ends[0]);
        close(stderr_ends[0]);

        if(execvp(command_list[0], command_list) == -1) {
            rb_raise(sse_ForkFailureError, "%s:%d (%d) execvp: %s\n", __FILE__, __LINE__, errno, strerror(errno));
        }
    } else {
        rb_raise(sse_FileNotFoundError, "%s:%d (%d) execvp: %s\n", __FILE__, __LINE__, errno, strerror(errno));
    }

    VALUE thunderfury_blessed_blade_of_the_windseeker = rb_ary_new2(3);
    rb_ary_store(thunderfury_blessed_blade_of_the_windseeker, 0, INT2NUM(42));
    rb_ary_store(thunderfury_blessed_blade_of_the_windseeker, 1, rb_str_new_cstr("this is stdout"));
    rb_ary_store(thunderfury_blessed_blade_of_the_windseeker, 2, rb_str_new_cstr("this is stderr"));
    return thunderfury_blessed_blade_of_the_windseeker;
}

/*
 * Initialize the module
*/

void Init_sse() {
    sse_module = rb_define_module("sse");

    sse_FileNotFoundError = rb_define_class_under(sse_module, "FileNotFoundError", rb_eStandardError);
    sse_ForkFailureError = rb_define_class_under(sse_module, "ForkFailureError", rb_eStandardError);
    sse_PipeFailureError = rb_define_class_under(sse_module, "PipeFailureError", rb_eStandardError);
    sse_WriteFailureError = rb_define_class_under(sse_module, "WriteFailureError", rb_eStandardError);
    sse_ReadFailureError = rb_define_class_under(sse_module, "ReadFailureError", rb_eStandardError);
    sse_WaitpidFailureError = rb_define_class_under(sse_module, "WaitpidFailureError", rb_eStandardError);
    sse_TimeoutError = rb_define_class_under(sse_module, "TimeoutError", rb_eStandardError);

    rb_define_global_function("execute_sh", rb_execute_sh, 3);
}
admins-MacBook-Pro-2:sse-ruby nchambers$ cat client.rb
require './sse'
result = execute_sh('', 10, 'hostname')
puts "=>#{result[0]}<=\n=>#{result[1]}<=\n=>#{result[2]}<=\n"
admins-MacBook-Pro-2:sse-ruby nchambers$ ruby client.rb
=>0<=
=>admins-MacBook-Pro-2.local
<=
=><=
admins-MacBook-Pro-2:sse-ruby nchambers$
admins-MacBook-Pro-2:sse-ruby nchambers$ irb
2.2.4 :001 > require './sse'
 => true
2.2.4 :002 > result = execute_sh('', 10, 'hostname')
 => [0, "\n.2.4 :003 > :in `execute_sh'\n\tfrom (irb):2\n\tfrom /Users/nchambers/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `<main>'\n", "irb(6804,0x7fffa88db3c0) malloc: *** error for object 0x7ff9ece81880: pointer being freed was not allocated\n*** set a breakpoint in malloc_error_break to debug\n"]
2.2.4 :003 > puts "=>#{result[0]}<=\n=>#{result[1]}<=\n=>#{result[2]}<=\n"
=>0<=
=>
.2.4 :003 > :in `execute_sh'
    from (irb):2
    from /Users/nchambers/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `<main>'
<=
=>irb(6804,0x7fffa88db3c0) malloc: *** error for object 0x7ff9ece81880: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
<=
 => nil
2.2.4 :004 >
arg_list[0] = malloc(strlen(arg));
strncpy(arg_list[0], arg, strlen(arg));
arg_list[arg_list_size] = malloc(strlen(arg));
strncpy(arg_list[arg_list_size], arg, strlen(arg));
arg_list[0] = malloc(strlen(arg) + 1);
strncpy(arg_list[0], arg, strlen(arg) + 1);
arg_list[0][strlen(arg)] = '\0';
arg_list[arg_list_size] = malloc(strlen(arg) + 1);
strncpy(arg_list[arg_list_size], arg, strlen(arg) + 1);
arg_list[arg_list_size][strlen(arg)] = '\0';
arg_list[0] = strdup(arg);
arg_list[arg_list_size] = strdup(arg);