Changeset 384

Show
Ignore:
Timestamp:
06/12/07 21:05:56 (2 years ago)
Author:
blackhedd
Message:

completed a serviceable popen implementation, including a mechanism for recovering the
subprocess PID (EventMachine::Connection#get_pid).

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • version_0/ext/cmain.cpp

    r383 r384  
    214214} 
    215215 
     216/*********************** 
     217evma_get_subprocess_pid 
     218***********************/ 
     219 
     220extern "C" int evma_get_subprocess_pid (const char *binding, pid_t *pid) 
     221{ 
     222        if (!EventMachine) 
     223                throw std::runtime_error ("not initialized"); 
     224        EventableDescriptor *ed = dynamic_cast <EventableDescriptor*> (Bindable_t::GetObject (binding)); 
     225        if (ed) { 
     226                return ed->GetSubprocessPid (pid) ? 1 : 0; 
     227        } 
     228        else 
     229                return 0; 
     230} 
     231 
    216232 
    217233/********************* 
  • version_0/ext/ed.h

    r381 r384  
    293293                time_t LastIo; 
    294294                int InactivityTimeout; 
    295                 FILE *MyStream; 
     295                //FILE *MyStream; 
    296296 
    297297                deque<OutboundPage> OutboundPages; 
  • version_0/ext/em.h

    r383 r384  
    7171                const char *CreateUnixDomainServer (const char*); 
    7272                const char *_OpenFileForWriting (const char*); 
    73                 const char *Popen (const char*, const char*); 
     73                //const char *Popen (const char*, const char*); 
    7474                const char *Socketpair (char* const*); 
    7575 
  • version_0/ext/eventmachine.h

    r383 r384  
    4545        void evma_start_tls (const char *binding); 
    4646        int evma_get_peername (const char *binding, struct sockaddr*); 
     47        int evma_get_subprocess_pid (const char *binding, pid_t*); 
    4748        int evma_send_data_to_connection (const char *binding, const char *data, int data_length); 
    4849        int evma_send_datagram (const char *binding, const char *data, int data_length, const char *address, int port); 
  • version_0/ext/pipe.cpp

    r381 r384  
    3030        LastIo (gCurrentLoopTime), 
    3131        InactivityTimeout (0), 
    32         MyStream (fp), 
     32        //MyStream (fp), 
    3333        OutboundDataSize (0), 
    3434        SubprocessPid (subpid) 
     
    5151 
    5252        /* As a virtual destructor, we come here before the base-class 
    53          * destructor that closes our file-descriptor. Calling pclose 
    54          * doesn't seem to bother the base-class destructor any, and it's 
    55          * required for cleaning up the subprocess zombie. 
    56          * Eventually we may need to refactor some of this stuff if there 
    57          * are undesirable interactions. 
    58          * Note that calling pclose on a still-running subprocess called 
    59          * with mode "r" will often cause the subprocess to catch SIGPIPE. 
    60          * This is part of the behavior of popen and not something EM is doing. 
     53         * destructor that closes our file-descriptor. 
     54         * We have to make sure the subprocess goes down (if it's not 
     55         * already down) and we have to reap the zombie. 
    6156         * 
    62          * Something weirder and worse happens with mode "w" - 
    63          * pclose WILL HANG irretrievably if the subprocess doesn't 
    64          * close when we tell it to. It will see a close on its end 
    65          * of the pipe (the read end), but that doesn't mean it will 
    66          * be written so as to exit when that happens. 
    67          * pclose waits for the subprocess to terminate. 
    68          * (Is there a flavor of popen that has a timeout or a no-hang 
    69          * option?) 
     57         * This implementation is PROVISIONAL and will surely be improved. 
     58         * The intention here is that we never block, hence the highly 
     59         * undesirable sleeps. But if we can't reap the subprocess even 
     60         * after sending it SIGKILL, then something is wrong and we 
     61         * throw a fatal exception, which is also not something we should 
     62         * be doing. 
    7063         * 
    71          * pclose returns the termination status of the subprocess. 
    72          * Someday we may need to make that available to the caller, 
    73          * possibly as an argument to the UNBOUND event. 
     64         * Eventually the right thing to do will be to have the reactor 
     65         * core respond to SIGCHLD by chaining a handler on top of the 
     66         * one Ruby may have installed, and dealing with a list of dead 
     67         * children that are pending cleanup. 
     68         * 
     69         * Since we want to have a signal processor integrated into the 
     70         * client-visible API, let's wait until that is done before cleaning 
     71         * this up. 
    7472         */ 
    75         pclose (MyStream); 
     73 
     74        struct timespec req = {0, 10000000}; 
     75        kill (SubprocessPid, SIGTERM); 
     76        nanosleep (&req, NULL); 
     77        if (waitpid (SubprocessPid, NULL, WNOHANG) == 0) { 
     78                kill (SubprocessPid, SIGKILL); 
     79                nanosleep (&req, NULL); 
     80                if (waitpid (SubprocessPid, NULL, WNOHANG) == 0) 
     81                        throw std::runtime_error ("unable to reap subprocess"); 
     82        } 
    7683} 
    7784 
  • version_0/ext/project.h

    r373 r384  
    4444#include <sys/un.h> 
    4545#include <sys/resource.h> 
     46#include <sys/wait.h> 
    4647#include <assert.h> 
    4748#include <unistd.h> 
  • version_0/ext/rubymain.cpp

    r383 r384  
    138138        if (evma_get_peername (StringValuePtr (signature), &s)) { 
    139139                return rb_str_new ((const char*)&s, sizeof(s)); 
     140        } 
     141 
     142        return Qnil; 
     143} 
     144 
     145/******************** 
     146t_get_subprocess_pid 
     147********************/ 
     148 
     149static VALUE t_get_subprocess_pid (VALUE self, VALUE signature) 
     150{ 
     151        pid_t pid; 
     152        if (evma_get_subprocess_pid (StringValuePtr (signature), &pid)) { 
     153                return INT2NUM (pid); 
    140154        } 
    141155 
     
    416430 
    417431        rb_define_module_function (EmModule, "get_peername", (VALUE(*)(...))t_get_peername, 1); 
     432        rb_define_module_function (EmModule, "get_subprocess_pid", (VALUE(*)(...))t_get_subprocess_pid, 1); 
    418433        rb_define_module_function (EmModule, "get_comm_inactivity_timeout", (VALUE(*)(...))t_get_comm_inactivity_timeout, 1); 
    419434        rb_define_module_function (EmModule, "set_comm_inactivity_timeout", (VALUE(*)(...))t_set_comm_inactivity_timeout, 2); 
  • version_0/lib/eventmachine.rb

    r383 r384  
    11791179        end 
    11801180 
     1181        # Returns the PID (kernel process identifier) of a subprocess 
     1182        # associated with this Connection object. For use with EventMachine#popen 
     1183        # and similar methods. Returns nil when there is no meaningful subprocess. 
     1184        #-- 
     1185        # 
     1186        def get_pid 
     1187                EventMachine::get_subprocess_pid @signature 
     1188        end 
     1189 
    11811190        # comm_inactivity_timeout returns the current value (in seconds) of the inactivity-timeout 
    11821191        # property of network-connection and datagram-socket objects. A nonzero value