Changeset 14663


Ignore:
Timestamp:
Jan 7, 2016, 3:28:58 PM (6 years ago)
Author:
mikedld
Message:

#5737: Retry if RPC server fails to bind to specified address

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/libtransmission/rpc-server.c

    r14644 r14663  
    5757    struct in_addr     bindAddress;
    5858    struct evhttp    * httpd;
     59    struct event     * start_retry_timer;
     60    int                start_retry_counter;
    5961    tr_session       * session;
    6062    char             * username;
     
    695697}
    696698
     699enum
     700{
     701  SERVER_START_RETRY_COUNT = 10,
     702  SERVER_START_RETRY_DELAY_STEP = 3,
     703  SERVER_START_RETRY_DELAY_INCREMENT = 5,
     704  SERVER_START_RETRY_MAX_DELAY = 60
     705};
     706
     707static void
     708startServer (void * vserver);
     709
     710static void
     711rpc_server_on_start_retry (evutil_socket_t   fd UNUSED,
     712                           short             type UNUSED,
     713                           void            * context)
     714{
     715  startServer (context);
     716}
     717
     718static int
     719rpc_server_start_retry (tr_rpc_server * server)
     720{
     721  int retry_delay = (server->start_retry_counter / SERVER_START_RETRY_DELAY_STEP + 1) *
     722                    SERVER_START_RETRY_DELAY_INCREMENT;
     723  retry_delay = MIN (retry_delay, SERVER_START_RETRY_MAX_DELAY);
     724
     725  if (server->start_retry_timer == NULL)
     726    server->start_retry_timer = evtimer_new (server->session->event_base,
     727                                             rpc_server_on_start_retry, server);
     728
     729  tr_timerAdd (server->start_retry_timer, retry_delay, 0);
     730  ++server->start_retry_counter;
     731
     732  return retry_delay;
     733}
     734
     735static void
     736rpc_server_start_retry_cancel (tr_rpc_server * server)
     737{
     738  if (server->start_retry_timer != NULL)
     739    {
     740      event_free (server->start_retry_timer);
     741      server->start_retry_timer = NULL;
     742    }
     743
     744  server->start_retry_counter = 0;
     745}
     746
    697747static void
    698748startServer (void * vserver)
    699749{
    700   tr_rpc_server * server  = vserver;
    701   tr_address addr;
    702 
    703   if (!server->httpd)
    704     {
    705       addr.type = TR_AF_INET;
    706       addr.addr.addr4 = server->bindAddress;
    707       server->httpd = evhttp_new (server->session->event_base);
    708       evhttp_bind_socket (server->httpd, tr_address_to_string (&addr), server->port);
    709       evhttp_set_gencb (server->httpd, handle_request, server);
    710     }
     750  tr_rpc_server * server = vserver;
     751
     752  if (server->httpd != NULL)
     753    return;
     754
     755  struct evhttp * httpd = evhttp_new (server->session->event_base);
     756  const char * address = tr_rpcGetBindAddress (server);
     757  const int port = server->port;
     758
     759  if (evhttp_bind_socket (httpd, address, port) == -1)
     760    {
     761      evhttp_free (httpd);
     762
     763      if (server->start_retry_counter < SERVER_START_RETRY_COUNT)
     764        {
     765          const int retry_delay = rpc_server_start_retry (server);
     766
     767          tr_logAddNamedDbg (MY_NAME, "Unable to bind to %s:%d, retrying in %d seconds",
     768                             address, port, retry_delay);
     769          return;
     770        }
     771
     772      tr_logAddNamedError (MY_NAME, "Unable to bind to %s:%d after %d attempts, giving up",
     773                           address, port, SERVER_START_RETRY_COUNT);
     774    }
     775  else
     776    {
     777      evhttp_set_gencb (httpd, handle_request, server);
     778      server->httpd = httpd;
     779
     780      tr_logAddNamedDbg (MY_NAME, "Started listening on %s:%d", address, port);
     781    }
     782
     783  rpc_server_start_retry_cancel (server);
    711784}
    712785
     
    714787stopServer (tr_rpc_server * server)
    715788{
    716   if (server->httpd)
    717     {
    718       evhttp_free (server->httpd);
    719       server->httpd = NULL;
    720     }
     789  rpc_server_start_retry_cancel (server);
     790
     791  struct evhttp * httpd = server->httpd;
     792  if (httpd == NULL)
     793    return;
     794
     795  const char * address = tr_rpcGetBindAddress (server);
     796  const int port = server->port;
     797
     798  server->httpd = NULL;
     799  evhttp_free (httpd);
     800
     801  tr_logAddNamedDbg (MY_NAME, "Stopped listening on %s:%d", address, port);
    721802}
    722803
Note: See TracChangeset for help on using the changeset viewer.