communication between worker processes

Leo P. junk at slact.net
Tue Oct 20 01:18:12 MSD 2009


Maxim Dounin wrote:
> Hello!
>
> On Mon, Oct 19, 2009 at 12:23:00AM -0400, Leo P. wrote:
>
>   
>> How might I be able to send a message or (custom) event to some
>> given worker process? I am storing pointers to requests (and the
>> workers that processed them) in shared memory for a module (
>> http://github.com/slact/nginx_http_push_module ), and need to alert
>> said workers to respond to said requests, from the context of a
>> location request handler in a module. (maybe using ngx_channel
>> stuff?)
>> I'd really appreciate any suggestions.
>>     
>
> There is no infrastructure for interprocess notifications in 
> nginx right now.  Basically it's the reason why there is no such 
> things as busy locks and so on.
>
> You may try to emulate it via e.g. message queue in shared memory 
> and periodic timer in each worker process to check it.  It's not 
> perfect, but probably will work for you.
>
> Maxim Dounin
>
>
>   
What about using ngx_add_channel_event on process initialization?
Is there anything obviously wrong with doing something like the following:

/*in init process callback*/
    ngx_socket_t my_channel=ngx_channel;
    /* is that the correct socket? what about
      ngx_processes[ngx_process_slot].channel[0] and
      ngx_processes[ngx_process_slot].channel[1] ?
      which could be used?
    */
    if (ngx_add_channel_event(cycle, my_channel, NGX_READ_EVENT, 
ngx_http_push_channel_handler) == NGX_ERROR) {
        exit(2);
    }
    //...

#define NGX_CMD_HTTP_PUSH_CHECK_MESSAGES 87; //some unlikely number. 
(looks hacky)

static void ngx_http_push_channel_handler(ngx_event_t *ev) {
    //mostly copied from ngx_channel_handler (os/unix/ngx_process_cycle.c)
    ngx_int_t          n;
    ngx_channel_t      ch;
    ngx_connection_t  *c;
    if (ev->timedout) {
        ev->timedout = 0;
        return;
    }
    c = ev->data;
    for ( ;; ) {
        n = ngx_read_channel(c->fd, &ch, sizeof(*ch), ev->log);
        if (n == NGX_ERROR) {
            if (ngx_event_flags & NGX_USE_EPOLL_EVENT) {
                ngx_del_conn(c, 0);
            }
            ngx_close_connection(c);
            return;
        }
        if ((ngx_event_flags & NGX_USE_EVENTPORT_EVENT) && 
(ngx_add_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR)) {
            return;
        }
        if (n == NGX_AGAIN) { return; }
  
        //the custom command now.
        if(ch.command==NGX_CMD_HTTP_PUSH_CHECK_MESSAGES) {
            //take a look at the message queue for this worker process 
in shared memory.
        }
    }
}

/* elsewhere, in a different worker process: */
if(/*some condition*/) {
    ngx_channel_t                  ch;
    ch.command = NGX_CMD_HTTP_PUSH_CHECK_MESSAGES;
    ch.fd = -1;
    
if((ngx_write_channel(ngx_processes[request_owner_worker_process_slot].channel[0 
/*or 1?*/], &ch, sizeof(*ch), some_log))!=NGX_OK) {
        //do some error handling
    }
}


Thanks again,
   - Leo






More information about the nginx mailing list