Skip to content

Instantly share code, notes, and snippets.

@clicube
Created March 11, 2013 04:16
Show Gist options
  • Save clicube/5131852 to your computer and use it in GitHub Desktop.
Save clicube/5131852 to your computer and use it in GitHub Desktop.
#include <sys/types.h>
#include <sys/wait.h>
#include <ruby.h>
/* include/ruby/ruby.h */
#ifndef IDTYPET2NUM
#define IDTYPET2NUM(v) INT2FIX(v)
#endif
#ifndef NUM2IDTYPET
#define NUM2IDTYPET(v) FIX2INT(v)
#endif
#ifndef IDT2NUM
#define IDT2NUM(v) UINT2NUM(v)
#endif
#ifndef NUM2IDT
#define NUM2IDT(v) NUM2UINT(v)
#endif
/* process.c */
struct waitid_arg {
idtype_t idtype;
id_t id;
siginfo_t* infop;
int options;
};
static void *
rb_waitid_blocking(void *data)
{
int result;
struct waitid_arg* arg = data;
result = waitid(arg->idtype, arg->id, arg->infop, arg->options);
return (void *)result;
}
VALUE rb_waitid(VALUE rb_self, VALUE rb_idtype, VALUE rb_id, VALUE rb_options)
{
int result;
siginfo_t info;
info.si_pid = 0;
struct waitid_arg arg;
arg.idtype = NUM2IDTYPET(rb_idtype);
arg.id = NUM2IDT(rb_id);
arg.infop = &info;
arg.options = FIX2INT(rb_options);
result = (int)rb_thread_call_without_gvl(rb_waitid_blocking, &arg,
RUBY_UBF_PROCESS, 0);
if(result < 0)
{
rb_sys_fail(0);
}
VALUE rb_result_class = rb_const_get(rb_mProcess, rb_intern("WaitidResult"));
VALUE rb_result = rb_funcall(rb_result_class, rb_intern("new"), 5,
PIDT2NUM(info.si_pid), UIDT2NUM(info.si_uid),
INT2NUM(info.si_signo), INT2NUM(info.si_status),
INT2NUM(info.si_code) );
return rb_result;
}
void Init_process_waitid(void)
{
rb_define_const(rb_mProcess, "P_PID", INT2FIX(P_PID));
rb_define_const(rb_mProcess, "P_PGID", INT2FIX(P_PGID));
rb_define_const(rb_mProcess, "P_ALL", INT2FIX(P_ALL));
rb_define_const(rb_mProcess, "WEXITED", INT2FIX(WEXITED));
rb_define_const(rb_mProcess, "WSTOPPED", INT2FIX(WSTOPPED));
rb_define_const(rb_mProcess, "WCONTINUED", INT2FIX(WCONTINUED));
//rb_define_const(rb_mProcess, "WNOHANG", INT2FIX(WNOHANG));
rb_define_const(rb_mProcess, "WNOWAIT", INT2FIX(WNOWAIT));
rb_define_const(rb_mProcess, "SIGCHLD", INT2FIX(SIGCHLD));
rb_define_const(rb_mProcess, "CLD_EXITED", INT2FIX(CLD_EXITED));
rb_define_const(rb_mProcess, "CLD_KILLED", INT2FIX(CLD_KILLED));
rb_define_const(rb_mProcess, "CLD_DUMPED", INT2FIX(CLD_DUMPED));
rb_define_const(rb_mProcess, "CLD_STOPPED", INT2FIX(CLD_STOPPED));
rb_define_const(rb_mProcess, "CLD_TRAPPED", INT2FIX(CLD_TRAPPED));
rb_define_const(rb_mProcess, "CLD_CONTINUED", INT2FIX(CLD_CONTINUED));
VALUE rb_waitid_result_class;
rb_waitid_result_class = rb_funcall(rb_cStruct, rb_intern("new"), 5,
ID2SYM(rb_intern("pid")), ID2SYM(rb_intern("uid")),
ID2SYM(rb_intern("signo")), ID2SYM(rb_intern("status")),
ID2SYM(rb_intern("code")) );
rb_define_const(rb_mProcess, "WaitidResult", rb_waitid_result_class);
rb_define_module_function(rb_mProcess, "waitid", rb_waitid, 3);
}
require 'mkmf'
if have_func("waitid") && have_type("id_t") && have_type("idtype_t")
create_makefile('process_waitid')
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment