Author: rhuijben
Date: Thu Oct 29 12:17:16 2015
New Revision: 1711233

URL: http://svn.apache.org/viewvc?rev=1711233&view=rev
Log:
Make the MockHTTP server stop using its http server with APR_SO_REUSEADDR,
as that will just allow multiple processes listening on the same port under
specific circumstances.

See http://stackoverflow.com/a/14388707/2094 for a great summary of how
this flag behaves on different operating systems. And in our case we
just want a unique port, with a mostly stable number.

* test/MockHTTPinC/MockHTTP_private.h
  (mhServCtx_t): Add default port variable.

* test/MockHTTPinC/MockHTTP_server.c
  (setupTCPServer): Set actual port. Drop use of APR_SO_REUSEADDR.
  (initServCtx): Tweak init.
  (_mhRunServerLoop): Avoid segfault when called after setupTCPServer fails.
  (mhServerByIDPortNr): Abort when somebody asks the port before
    setting up the server.
  (set_server_port): Update the new port number.

Modified:
    serf/trunk/test/MockHTTPinC/MockHTTP_private.h
    serf/trunk/test/MockHTTPinC/MockHTTP_server.c

Modified: serf/trunk/test/MockHTTPinC/MockHTTP_private.h
URL: 
http://svn.apache.org/viewvc/serf/trunk/test/MockHTTPinC/MockHTTP_private.h?rev=1711233&r1=1711232&r2=1711233&view=diff
==============================================================================
--- serf/trunk/test/MockHTTPinC/MockHTTP_private.h (original)
+++ serf/trunk/test/MockHTTPinC/MockHTTP_private.h Thu Oct 29 12:17:16 2015
@@ -113,6 +113,7 @@ struct mhServCtx_t {
     const char *hostname;
     const char *serverID;      /* unique id for this server */
     apr_port_t port;
+    apr_port_t default_port;
     const char *alpn;
     apr_pollset_t *pollset;
     apr_socket_t *skt;         /* Server listening socket */

Modified: serf/trunk/test/MockHTTPinC/MockHTTP_server.c
URL: 
http://svn.apache.org/viewvc/serf/trunk/test/MockHTTPinC/MockHTTP_server.c?rev=1711233&r1=1711232&r2=1711233&view=diff
==============================================================================
--- serf/trunk/test/MockHTTPinC/MockHTTP_server.c (original)
+++ serf/trunk/test/MockHTTPinC/MockHTTP_server.c Thu Oct 29 12:17:16 2015
@@ -193,6 +193,8 @@ static apr_status_t setupTCPServer(mhSer
     apr_pool_t *pool = ctx->pool;
     apr_status_t status;
 
+    ctx->port = ctx->default_port;
+
     while (1) {
         STATUSERR(apr_sockaddr_info_get(&serv_addr, ctx->hostname,
                                         APR_UNSPEC, ctx->port, 0,
@@ -205,7 +207,17 @@ static apr_status_t setupTCPServer(mhSer
 
         STATUSERR(apr_socket_opt_set(ctx->skt, APR_SO_NONBLOCK, 1));
         STATUSERR(apr_socket_timeout_set(ctx->skt, 0));
-        STATUSERR(apr_socket_opt_set(ctx->skt, APR_SO_REUSEADDR, 1));
+        /* We used to call apr_socket_opt_set(ctx->skt, APR_SO_REUSEADDR, 1),
+           but that is severly broken when we run multiple tests in parallel,
+           as that may just listen on a port where another process is
+           listening too.
+
+           See http://stackoverflow.com/a/14388707/2094
+
+           Instead of trying to work around the limitations per platform
+           by using specific flags, the best fix is to just *not* use
+           this option and use a different port if necessary.
+         */
 
         /* Try the next port until bind succeeds */
         status = apr_socket_bind(ctx->skt, serv_addr);
@@ -292,7 +304,8 @@ initServCtx(const MockHTTP *mh, const ch
     ctx->pool = pool;
     ctx->mh = mh;
     ctx->hostname = apr_pstrdup(pool, hostname);
-    ctx->port = port;
+    ctx->default_port = port;
+    ctx->port = 0;
     ctx->clients = apr_array_make(pool, 5, sizeof(_mhClientCtx_t *));
     ctx->reqsReceived = apr_array_make(pool, 5, sizeof(mhRequest_t *));
     /* Default settings */
@@ -1547,6 +1560,12 @@ apr_status_t _mhRunServerLoop(mhServCtx_
     const apr_pollfd_t *desc;
     apr_status_t status;
 
+    if (!ctx->pollset) {
+        /* Somebody ignored the result of mhStartServer().
+           ... Not that hard given that it returns void */
+        return APR_EINCOMPLETE;
+    }
+
     if (ctx->reqState == FullReqReceived)
         ctx->reqState = NoReqsReceived;
 #if 0
@@ -1832,8 +1851,12 @@ mhSetServerMaxRequestsPerConn(mhServCtx_
 unsigned int mhServerByIDPortNr(const MockHTTP *mh, const char *serverID)
 {
     mhServCtx_t *ctx = mhFindServerByID(mh, serverID);
-    if (ctx)
+
+    if (ctx) {
+        if (!ctx->port)
+            abort();
         return ctx->port;
+    }
     return 0;
 }
 
@@ -1852,7 +1875,7 @@ unsigned int mhProxyPortNr(const MockHTT
  */
 static bool set_server_port(const mhServerSetupBldr_t *ssb, mhServCtx_t *ctx)
 {
-    ctx->port = ssb->ibaton;
+    ctx->default_port = ssb->ibaton;
     return YES;
 }
 


Reply via email to