diff --git a/include/proto/shctx.h b/include/proto/shctx.h index a84e4a677..e0c695d1b 100644 --- a/include/proto/shctx.h +++ b/include/proto/shctx.h @@ -28,6 +28,9 @@ #define SHCTX_APPNAME "haproxy" #endif +#define SHCTX_E_ALLOC_CACHE -1 +#define SHCTX_E_INIT_LOCK -2 + /* Allocate shared memory context. * is the number of allocated blocks into cache (default 128 bytes) * A block is large enough to contain a classic session (without client cert) diff --git a/src/cfgparse.c b/src/cfgparse.c index c4f092fa9..7176b5943 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -6744,6 +6744,8 @@ out_uri_auth_compat: * remains NULL so that listeners can later detach. */ list_for_each_entry(bind_conf, &curproxy->conf.bind, by_fe) { + int alloc_ctx; + if (!bind_conf->is_ssl) { if (bind_conf->default_ctx) { Warning("Proxy '%s': A certificate was specified but SSL was not enabled on bind '%s' at [%s:%d] (use 'ssl').\n", @@ -6758,10 +6760,18 @@ out_uri_auth_compat: continue; } - if (shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0) < 0) { - Alert("Unable to allocate SSL session cache.\n"); - cfgerr++; - continue; + alloc_ctx = shared_context_init(global.tune.sslcachesize, (global.nbproc > 1) ? 1 : 0); + if (alloc_ctx < 0) { + if (alloc_ctx == SHCTX_E_INIT_LOCK) { + Warning("Unable to init lock for the shared SSL session cache. Falling back to private cache.\n"); + alloc_ctx = shared_context_init(global.tune.sslcachesize, 0); + } + + if (alloc_ctx < 0) { + Alert("Unable to allocate SSL session cache.\n"); + cfgerr++; + continue; + } } /* initialize all certificate contexts */ diff --git a/src/shctx.c b/src/shctx.c index f259b9c1c..86e605651 100644 --- a/src/shctx.c +++ b/src/shctx.c @@ -532,19 +532,36 @@ int shared_context_init(int size, int shared) PROT_READ | PROT_WRITE, maptype | MAP_ANON, -1, 0); if (!shctx || shctx == MAP_FAILED) { shctx = NULL; - return -1; + return SHCTX_E_ALLOC_CACHE; } #ifndef USE_PRIVATE_CACHE + if (maptype == MAP_SHARED) { #ifdef USE_SYSCALL_FUTEX - shctx->waiters = 0; + shctx->waiters = 0; #else - pthread_mutexattr_init(&attr); - pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED); - pthread_mutex_init(&shctx->mutex, &attr); + if (pthread_mutexattr_init(&attr)) { + munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block))); + shctx = NULL; + return SHCTX_E_INIT_LOCK; + } + + if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { + pthread_mutexattr_destroy(&attr); + munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block))); + shctx = NULL; + return SHCTX_E_INIT_LOCK; + } + + if (pthread_mutex_init(&shctx->mutex, &attr)) { + pthread_mutexattr_destroy(&attr); + munmap(shctx, sizeof(struct shared_context)+(size*sizeof(struct shared_block))); + shctx = NULL; + return SHCTX_E_INIT_LOCK; + } #endif - if (maptype == MAP_SHARED) use_shared_mem = 1; + } #endif memset(&shctx->active.data.session.key, 0, sizeof(struct ebmb_node));