diff --git a/mrbgem.rake b/mrbgem.rake index 26a8065..8125e47 100644 --- a/mrbgem.rake +++ b/mrbgem.rake @@ -1,4 +1,5 @@ -MRuby::Gem::Specification.new('mruby-process') do |spec| +MRuby::Gem::Specification.new('mruby-process-win32') do |spec| + # based on https://github.com/iij/mruby-process spec.license = 'MIT' spec.authors = 'mruby developers' diff --git a/src/process.c b/src/process.c index 50595f9..a302be2 100644 --- a/src/process.c +++ b/src/process.c @@ -13,16 +13,69 @@ #include "error.h" #include +#ifndef _WIN32 #include #include #include +#else +#include +#endif #include #include #include #include +#ifndef _MSC_VER #include +#endif #include +#ifdef _WIN32 +static const char* +emsg(DWORD err) +{ + static char buf[256]; + if (err == 0) return "succeeded"; + FormatMessage( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + err, + MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US), + buf, + sizeof buf, + NULL); + return buf; +} + +#ifndef SIGKILL +#define SIGKILL 9 +#endif + +int +kill(int pid, int sig) +{ + HANDLE handle; + switch (sig) { + case SIGTERM: + case SIGKILL: + case SIGINT: + handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + if (!TerminateProcess(handle, 1)) + return -1; + default: + return -1; + } + return 0; +} + +unsigned int +sleep(unsigned int seconds) +{ + Sleep(seconds * 1000); + return seconds; +} + +#endif + mrb_value mrb_f_kill(mrb_state *mrb, mrb_value klass) { @@ -59,6 +112,7 @@ mrb_f_kill(mrb_state *mrb, mrb_value klass) static mrb_value mrb_f_fork(mrb_state *mrb, mrb_value klass) { +#ifndef _WIN32 mrb_value b, result; int pid; @@ -79,6 +133,10 @@ mrb_f_fork(mrb_state *mrb, mrb_value klass) default: return mrb_fixnum_value(pid); } +#else + mrb_raise(mrb, E_RUNTIME_ERROR, emsg(ERROR_CALL_NOT_IMPLEMENTED)); + return mrb_nil_value(); +#endif } static int @@ -86,6 +144,7 @@ mrb_waitpid(int pid, int flags, int *st) { int result; +#ifndef _WIN32 retry: result = waitpid(pid, st, flags); if (result < 0) { @@ -94,6 +153,10 @@ mrb_waitpid(int pid, int flags, int *st) } return -1; } +#else + HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); + result = WaitForSingleObject(handle, INFINITE) == WAIT_OBJECT_0 ? 0 : -1; +#endif return result; } @@ -135,8 +198,12 @@ mrb_f_sleep(mrb_state *mrb, mrb_value klass) tv.tv_usec = (mrb_float(argv[0]) - tv.tv_sec) * 1000000.0; } - +#ifdef _WIN32 + n = tv.tv_sec * 1000 + tv.tv_usec / 1000; + Sleep(n); +#else n = select(0, 0, 0, 0, &tv); +#endif if (n < 0) mrb_sys_fail(mrb, "mrb_f_sleep failed"); } else { @@ -157,7 +224,9 @@ mrb_f_system(mrb_state *mrb, mrb_value klass) mrb_value *argv, pname; const char *path; int argc; +#ifdef SIGCHLD RETSIGTYPE (*chfunc)(int); +#endif fflush(stdout); fflush(stderr); @@ -174,9 +243,14 @@ mrb_f_system(mrb_state *mrb, mrb_value klass) path = mrb_string_value_cstr(mrb, &pname); ret = system(path); +#ifndef _WIN32 if (WIFEXITED(ret) && WEXITSTATUS(ret) == 0) { return mrb_true_value(); } +#else + if (ret != -1) + return mrb_true_value(); +#endif return mrb_false_value(); } @@ -210,11 +284,16 @@ mrb_f_pid(mrb_state *mrb, mrb_value klass) mrb_value mrb_f_ppid(mrb_state *mrb, mrb_value klass) { +#ifndef _WIN32 return mrb_fixnum_value((mrb_int)getppid()); +#else + mrb_raise(mrb, E_RUNTIME_ERROR, emsg(ERROR_CALL_NOT_IMPLEMENTED)); + return mrb_nil_value(); +#endif } void -mrb_mruby_process_gem_init(mrb_state *mrb) +mrb_mruby_process_win32_gem_init(mrb_state *mrb) { struct RClass *p; @@ -233,6 +312,6 @@ mrb_mruby_process_gem_init(mrb_state *mrb) } void -mrb_mruby_process_gem_final(mrb_state *mrb) +mrb_mruby_process_win32_gem_final(mrb_state *mrb) { }