static VALUE daemon_mainloop_ensure(VALUE self) { int i; // Signal both the ruby thread and service_main thread to terminate SetEvent(hStopEvent); // Wait for ALL ruby threads to exit for(i=1; TRUE; i++) { VALUE list = rb_funcall(rb_cThread, rb_intern("list"), 0); if(RARRAY_LEN(list) <= 1) break; // This is another ugly polling loop, be as polite as possible rb_thread_polling(); SetTheServiceStatus(SERVICE_STOP_PENDING, 0, i, 1000); } // Only one ruby thread SetEvent(hStopCompletedEvent); // Wait for the thread to stop BEFORE we close the hStopEvent handle WaitForSingleObject(hThread, INFINITE); // Close the event handle, ignoring failures. We may be cleaning up // after an exception, so let that exception fall through. CloseHandle(hStopEvent); return self; }
VALUE Ruby_Service_Ctrl(VALUE self) { while (WaitForSingleObject(hStopEvent,0) == WAIT_TIMEOUT) { __try { EnterCriticalSection(&csControlCode); // Check to see if anything interesting has been signaled if (waiting_control_code != IDLE_CONTROL_CODE) { if (waiting_control_code != SERVICE_CONTROL_STOP) { // if there is a code, create a ruby thread to deal with it // this might be over engineering the solution, but I don't // want to block Service_Ctrl longer than necessary and the // critical section will block it. VALUE EventHookHash = rb_ivar_get(self, rb_intern("@event_hooks")); if(EventHookHash != Qnil){ VALUE val = rb_hash_aref(EventHookHash, INT2NUM(waiting_control_code)); if(val != Qnil) rb_thread_create(Service_Event_Dispatch, (void*) val); } } else { break; } waiting_control_code = IDLE_CONTROL_CODE; } } __finally { LeaveCriticalSection(&csControlCode); } // This is an ugly polling loop, be as polite as possible rb_thread_polling(); __end_finally } // force service_stop call { VALUE EventHookHash = rb_ivar_get(self, rb_intern("@event_hooks")); if(EventHookHash != Qnil){ VALUE val = rb_hash_aref(EventHookHash, INT2NUM(SERVICE_CONTROL_STOP)); if(val!=Qnil) rb_thread_create(Service_Event_Dispatch, (void*) val); } } return Qnil; }
VALUE rb_f_kill(int argc, VALUE *argv) { #ifndef HAS_KILLPG #define killpg(pg, sig) kill(-(pg), sig) #endif int negative = 0; int sig; int i; const char *s; rb_secure(2); if (argc < 2) rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)"); switch (TYPE(argv[0])) { case T_FIXNUM: sig = FIX2INT(argv[0]); break; case T_SYMBOL: s = rb_id2name(SYM2ID(argv[0])); if (!s) rb_raise(rb_eArgError, "bad signal"); goto str_signal; case T_STRING: s = RSTRING_PTR(argv[0]); if (s[0] == '-') { negative++; s++; } str_signal: if (strncmp("SIG", s, 3) == 0) s += 3; if((sig = signm2signo(s)) == 0) rb_raise(rb_eArgError, "unsupported name `SIG%s'", s); if (negative) sig = -sig; break; default: { VALUE str; str = rb_check_string_type(argv[0]); if (!NIL_P(str)) { s = RSTRING_PTR(str); goto str_signal; } rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0])); } break; } if (sig < 0) { sig = -sig; for (i=1; i<argc; i++) { if (killpg(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } else { for (i=1; i<argc; i++) { if (kill(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } rb_thread_polling(); return INT2FIX(i-1); }
VALUE rb_f_kill(VALUE self, SEL sel, int argc, VALUE *argv) { int negative = 0; int sig; int i; int type; const char *s = NULL; rb_secure(2); if (argc < 2) rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)"); type = TYPE(argv[0]); if (type == T_FIXNUM) { sig = FIX2INT(argv[0]); } else { if (type == T_SYMBOL) { s = rb_sym2name(argv[0]); if (!s) rb_raise(rb_eArgError, "bad signal"); } else if (type == T_STRING) { s = RSTRING_PTR(argv[0]); if (s[0] == '-') { negative++; s++; } } else { VALUE str; str = rb_check_string_type(argv[0]); if (!NIL_P(str)) { s = RSTRING_PTR(str); } } if (s == NULL) rb_raise(rb_eArgError, "bad signal type %s", rb_obj_classname(argv[0])); if (strncmp("SIG", s, 3) == 0) s += 3; if ((sig = signm2signo(s)) == 0) rb_raise(rb_eArgError, "unsupported name `SIG%s'", s); if (negative) sig = -sig; } if (sig < 0) { sig = -sig; for (i = 1; i < argc; i++) { if (killpg(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } else { for (i = 1; i < argc; i++) { if (kill(NUM2PIDT(argv[i]), sig) < 0) rb_sys_fail(0); } } rb_thread_polling(); return INT2FIX(i - 1); }