changeset 2720:b3b8c66bd520

support attaching to an existent Win32 shared memory
author Igor Sysoev <igor@sysoev.ru>
date Sat, 18 Apr 2009 19:27:28 +0000
parents 9237cf8b400b
children 8e720b7fe6d2
files src/core/ngx_cycle.c src/core/ngx_slab.h src/event/ngx_event.c src/event/ngx_event_openssl.c src/http/modules/ngx_http_limit_req_module.c src/http/modules/ngx_http_limit_zone_module.c src/http/ngx_http_cache.h src/http/ngx_http_file_cache.c src/os/unix/ngx_shmem.h src/os/win32/ngx_os.h src/os/win32/ngx_shmem.c src/os/win32/ngx_shmem.h src/os/win32/ngx_win32_init.c
diffstat 13 files changed, 220 insertions(+), 155 deletions(-) [+]
line wrap: on
line diff
--- a/src/core/ngx_cycle.c
+++ b/src/core/ngx_cycle.c
@@ -9,9 +9,11 @@
 #include <ngx_event.h>
 
 
-static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
 static void ngx_destroy_cycle_pools(ngx_conf_t *conf);
 static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2);
+static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle,
+    ngx_shm_zone_t *shm_zone);
+static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
 static void ngx_clean_old_cycles(ngx_event_t *ev);
 
 
@@ -44,7 +46,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
 {
     void                *rv;
     char               **senv, **env;
-    u_char              *lock_file;
     ngx_uint_t           i, n;
     ngx_log_t           *log;
     ngx_time_t          *tp;
@@ -52,7 +53,6 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
     ngx_pool_t          *pool;
     ngx_cycle_t         *cycle, **old;
     ngx_shm_zone_t      *shm_zone, *oshm_zone;
-    ngx_slab_pool_t     *shpool;
     ngx_list_part_t     *part, *opart;
     ngx_open_file_t     *file;
     ngx_listening_t     *ls, *nls;
@@ -470,39 +470,13 @@ ngx_init_cycle(ngx_cycle_t *old_cycle)
             goto failed;
         }
 
-        shpool = (ngx_slab_pool_t *) shm_zone[i].shm.addr;
-
-        shpool->end = shm_zone[i].shm.addr + shm_zone[i].shm.size;
-        shpool->min_shift = 3;
-
-#if (NGX_HAVE_ATOMIC_OPS)
-
-        lock_file = NULL;
-
-#else
-
-        lock_file = ngx_pnalloc(cycle->pool,
-                               cycle->lock_file.len + shm_zone[i].shm.name.len);
+        if (!shm_zone[i].shm.exists) {
 
-        if (lock_file == NULL) {
-            goto failed;
+	    if (ngx_init_zone_pool(cycle, &shm_zone[i]) != NGX_OK) {
+		goto failed;
+	    }
         }
 
-        (void) ngx_cpystrn(ngx_cpymem(lock_file, cycle->lock_file.data,
-                                      cycle->lock_file.len),
-                           shm_zone[i].shm.name.data,
-                           shm_zone[i].shm.name.len + 1);
-
-#endif
-
-        if (ngx_shmtx_create(&shpool->mutex, (void *) &shpool->lock, lock_file)
-            != NGX_OK)
-        {
-            goto failed;
-        }
-
-        ngx_slab_init(shpool);
-
         if (shm_zone[i].init(&shm_zone[i], NULL) != NGX_OK) {
             goto failed;
         }
@@ -919,6 +893,42 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, s
 }
 
 
+static ngx_int_t
+ngx_init_zone_pool(ngx_cycle_t *cycle, ngx_shm_zone_t *zn)
+{
+    u_char           *file;
+    ngx_slab_pool_t  *sp;
+
+    sp = (ngx_slab_pool_t *) zn->shm.addr;
+
+    sp->end = zn->shm.addr + zn->shm.size;
+    sp->min_shift = 3;
+
+#if (NGX_HAVE_ATOMIC_OPS)
+
+    file = NULL;
+
+#else
+
+    file = ngx_pnalloc(cycle->pool, cycle->lock_file.len + zn->shm.name.len);
+    if (file == NULL) {
+	return NGX_ERROR;
+    }
+
+    (void) ngx_sprintf(file, "%V%V%Z", &cycle->lock_file, &zn->shm.name);
+
+#endif
+
+    if (ngx_shmtx_create(&sp->mutex, (void *) &sp->lock, file) != NGX_OK) {
+	return NGX_ERROR;
+    }
+
+    ngx_slab_init(sp);
+
+    return NGX_OK;
+}
+
+
 #if !(NGX_WIN32)
 
 ngx_int_t
@@ -1216,6 +1226,7 @@ ngx_shared_memory_add(ngx_conf_t *cf, ng
     shm_zone->shm.log = cf->cycle->log;
     shm_zone->shm.size = size;
     shm_zone->shm.name = *name;
+    shm_zone->shm.exists = 0;
     shm_zone->init = NULL;
     shm_zone->tag = tag;
 
--- a/src/core/ngx_slab.h
+++ b/src/core/ngx_slab.h
@@ -37,6 +37,8 @@ typedef struct {
 
     u_char           *log_ctx;
     u_char            zero;
+
+    void             *data;
 } ngx_slab_pool_t;
 
 
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -506,6 +506,8 @@ ngx_event_module_init(ngx_cycle_t *cycle
 #endif
 
     shm.size = size;
+    shm.name.len = sizeof("nginx_shared_zone");
+    shm.name.data = (u_char *) "nginx_shared_zone";
     shm.log = cycle->log;
 
     if (ngx_shm_alloc(&shm) != NGX_OK) {
@@ -535,7 +537,7 @@ ngx_event_module_init(ngx_cycle_t *cycle
 
 #endif
 
-    *ngx_connection_counter = 1;
+    (void) ngx_atomic_cmp_set(ngx_connection_counter, 0, 1);
 
     ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    "counter: %p, %d",
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -1421,6 +1421,11 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
         return NGX_OK;
     }
 
+    if (shm_zone->shm.exists) {
+        shm_zone->data = data;
+        return NGX_OK;
+    }
+
     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
     cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_session_cache_t));
@@ -1428,6 +1433,9 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
         return NGX_ERROR;
     }
 
+    shpool->data = cache;
+    shm_zone->data = cache;
+
     ngx_rbtree_init(&cache->session_rbtree, &cache->sentinel,
                     ngx_ssl_session_rbtree_insert_value);
 
@@ -1443,8 +1451,6 @@ ngx_ssl_session_cache_init(ngx_shm_zone_
     ngx_sprintf(shpool->log_ctx, " in SSL session shared cache \"%V\"%Z",
                 &shm_zone->shm.name);
 
-    shm_zone->data = cache;
-
     return NGX_OK;
 }
 
--- a/src/http/modules/ngx_http_limit_req_module.c
+++ b/src/http/modules/ngx_http_limit_req_module.c
@@ -10,30 +10,39 @@
 
 
 typedef struct {
-    u_char              color;
-    u_char              dummy;
-    u_short             len;
-    ngx_queue_t         queue;
-    ngx_msec_t          last;
-    ngx_uint_t          excess; /* integer value, 1 corresponds to 0.001 r/s */
-    u_char              data[1];
+    u_char                       color;
+    u_char                       dummy;
+    u_short                      len;
+    ngx_queue_t                  queue;
+    ngx_msec_t                   last;
+    /* integer value, 1 corresponds to 0.001 r/s */
+    ngx_uint_t                   excess;
+    u_char                       data[1];
 } ngx_http_limit_req_node_t;
 
 
 typedef struct {
-    ngx_rbtree_t       *rbtree;
-    ngx_queue_t        *queue;
-    ngx_slab_pool_t    *shpool;
-    ngx_uint_t          rate;   /* integer value, 1 corresponds to 0.001 r/s */
-    ngx_int_t           index;
-    ngx_str_t           var;
+    ngx_rbtree_t                  rbtree;
+    ngx_rbtree_node_t             sentinel;
+    ngx_queue_t                   queue;
+} ngx_http_limit_req_shctx_t;
+
+
+typedef struct {
+    ngx_http_limit_req_shctx_t  *sh;
+    ngx_slab_pool_t             *shpool;
+    /* integer value, 1 corresponds to 0.001 r/s */
+    ngx_uint_t                   rate;
+    ngx_int_t                    index;
+    ngx_str_t                    var;
 } ngx_http_limit_req_ctx_t;
 
 
 typedef struct {
-    ngx_shm_zone_t     *shm_zone;
-    ngx_uint_t          burst;  /* integer value, 1 corresponds to 0.001 r/s */
-    ngx_uint_t          nodelay;/* unsigned  nodelay:1 */
+    ngx_shm_zone_t              *shm_zone;
+    /* integer value, 1 corresponds to 0.001 r/s */
+    ngx_uint_t                   burst;
+    ngx_uint_t                   nodelay;/* unsigned  nodelay:1 */
 } ngx_http_limit_req_conf_t;
 
 
@@ -163,7 +172,7 @@ ngx_http_limit_req_handler(ngx_http_requ
     if (lr) {
         ngx_queue_remove(&lr->queue);
 
-        ngx_queue_insert_head(ctx->queue, &lr->queue);
+        ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
 
         excess = lr->excess;
 
@@ -239,9 +248,9 @@ ngx_http_limit_req_handler(ngx_http_requ
     lr->excess = 0;
     ngx_memcpy(lr->data, vv->data, len);
 
-    ngx_rbtree_insert(ctx->rbtree, node);
+    ngx_rbtree_insert(&ctx->sh->rbtree, node);
 
-    ngx_queue_insert_head(ctx->queue, &lr->queue);
+    ngx_queue_insert_head(&ctx->sh->queue, &lr->queue);
 
 done:
 
@@ -324,8 +333,8 @@ ngx_http_limit_req_lookup(ngx_http_limit
 
     ctx = lrcf->shm_zone->data;
 
-    node = ctx->rbtree->root;
-    sentinel = ctx->rbtree->sentinel;
+    node = ctx->sh->rbtree.root;
+    sentinel = ctx->sh->rbtree.sentinel;
 
     while (node != sentinel) {
 
@@ -411,11 +420,11 @@ ngx_http_limit_req_expire(ngx_http_limit
 
     while (n < 3) {
 
-        if (ngx_queue_empty(ctx->queue)) {
+        if (ngx_queue_empty(&ctx->sh->queue)) {
             return;
         }
 
-        q = ngx_queue_last(ctx->queue);
+        q = ngx_queue_last(&ctx->sh->queue);
 
         lr = ngx_queue_data(q, ngx_http_limit_req_node_t, queue);
 
@@ -440,7 +449,7 @@ ngx_http_limit_req_expire(ngx_http_limit
         node = (ngx_rbtree_node_t *)
                    ((u_char *) lr - offsetof(ngx_rbtree_node_t, color));
 
-        ngx_rbtree_delete(ctx->rbtree, node);
+        ngx_rbtree_delete(&ctx->sh->rbtree, node);
 
         ngx_slab_free_locked(ctx->shpool, node);
     }
@@ -453,7 +462,6 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
     ngx_http_limit_req_ctx_t  *octx = data;
 
     size_t                     len;
-    ngx_rbtree_node_t         *sentinel;
     ngx_http_limit_req_ctx_t  *ctx;
 
     ctx = shm_zone->data;
@@ -467,8 +475,7 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
             return NGX_ERROR;
         }
 
-        ctx->rbtree = octx->rbtree;
-        ctx->queue = octx->queue;
+        ctx->sh = octx->sh;
         ctx->shpool = octx->shpool;
 
         return NGX_OK;
@@ -476,25 +483,23 @@ ngx_http_limit_req_init_zone(ngx_shm_zon
 
     ctx->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
-    ctx->rbtree = ngx_slab_alloc(ctx->shpool, sizeof(ngx_rbtree_t));
-    if (ctx->rbtree == NULL) {
-        return NGX_ERROR;
+    if (shm_zone->shm.exists) {
+        ctx->sh = ctx->shpool->data;
+
+        return NGX_OK;
     }
 
-    sentinel = ngx_slab_alloc(ctx->shpool, sizeof(ngx_rbtree_node_t));
-    if (sentinel == NULL) {
+    ctx->sh = ngx_slab_alloc(ctx->shpool, sizeof(ngx_http_limit_req_shctx_t));
+    if (ctx->sh == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_rbtree_init(ctx->rbtree, sentinel,
+    ctx->shpool->data = ctx->sh;
+
+    ngx_rbtree_init(&ctx->sh->rbtree, &ctx->sh->sentinel,
                     ngx_http_limit_req_rbtree_insert_value);
 
-    ctx->queue = ngx_slab_alloc(ctx->shpool, sizeof(ngx_queue_t));
-    if (ctx->queue == NULL) {
-        return NGX_ERROR;
-    }
-
-    ngx_queue_init(ctx->queue);
+    ngx_queue_init(&ctx->sh->queue);
 
     len = sizeof(" in limit_req zone \"\"") + shm_zone->shm.name.len;
 
--- a/src/http/modules/ngx_http_limit_zone_module.c
+++ b/src/http/modules/ngx_http_limit_zone_module.c
@@ -339,11 +339,19 @@ ngx_http_limit_zone_init_zone(ngx_shm_zo
 
     shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
+    if (shm_zone->shm.exists) {
+        ctx->rbtree = shpool->data;
+
+        return NGX_OK;
+    }
+
     ctx->rbtree = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_t));
     if (ctx->rbtree == NULL) {
         return NGX_ERROR;
     }
 
+    shpool->data = ctx->rbtree;
+
     sentinel = ngx_slab_alloc(shpool, sizeof(ngx_rbtree_node_t));
     if (sentinel == NULL) {
         return NGX_ERROR;
--- a/src/http/ngx_http_cache.h
+++ b/src/http/ngx_http_cache.h
@@ -94,16 +94,21 @@ typedef struct {
 } ngx_http_file_cache_header_t;
 
 
+typedef struct {
+    ngx_rbtree_t                     rbtree;
+    ngx_rbtree_node_t                sentinel;
+    ngx_queue_t                      queue;
+    ngx_atomic_t                     cold;
+    off_t                            size;
+} ngx_http_file_cache_sh_t;
+
+
 struct ngx_http_file_cache_s {
-    ngx_rbtree_t                    *rbtree;
-    ngx_queue_t                     *queue;
+    ngx_http_file_cache_sh_t        *sh;
     ngx_slab_pool_t                 *shpool;
 
     ngx_path_t                      *path;
 
-    ngx_atomic_t                    *cold;
-    off_t                           *size;
-
     off_t                            max_size;
     size_t                           bsize;
 
--- a/src/http/ngx_http_file_cache.c
+++ b/src/http/ngx_http_file_cache.c
@@ -44,7 +44,6 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
     ngx_http_file_cache_t  *ocache = data;
 
     size_t                  len;
-    ngx_rbtree_node_t      *sentinel;
     ngx_http_file_cache_t  *cache;
 
     cache = shm_zone->data;
@@ -60,11 +59,9 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
             return NGX_ERROR;
         }
 
-        cache->rbtree = ocache->rbtree;
-        cache->queue = ocache->queue;
+        cache->sh = ocache->sh;
+
         cache->shpool = ocache->shpool;
-        cache->cold = ocache->cold;
-        cache->size = ocache->size;
         cache->bsize = ocache->bsize;
 
         cache->max_size /= cache->bsize;
@@ -74,39 +71,27 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
 
     cache->shpool = (ngx_slab_pool_t *) shm_zone->shm.addr;
 
-    cache->rbtree = ngx_slab_alloc(cache->shpool, sizeof(ngx_rbtree_t));
-    if (cache->rbtree == NULL) {
-        return NGX_ERROR;
+    if (shm_zone->shm.exists) {
+        cache->sh = cache->shpool->data;
+        cache->bsize = ngx_fs_bsize(cache->path->name.data);
+
+        return NGX_OK;
     }
 
-    sentinel = ngx_slab_alloc(cache->shpool, sizeof(ngx_rbtree_node_t));
-    if (sentinel == NULL) {
+    cache->sh = ngx_slab_alloc(cache->shpool, sizeof(ngx_http_file_cache_sh_t));
+    if (cache->sh == NULL) {
         return NGX_ERROR;
     }
 
-    ngx_rbtree_init(cache->rbtree, sentinel,
+    cache->shpool->data = cache->sh;
+
+    ngx_rbtree_init(&cache->sh->rbtree, &cache->sh->sentinel,
                     ngx_http_file_cache_rbtree_insert_value);
 
-    cache->queue = ngx_slab_alloc(cache->shpool, sizeof(ngx_queue_t));
-    if (cache->queue == NULL) {
-        return NGX_ERROR;
-    }
-
-    ngx_queue_init(cache->queue);
+    ngx_queue_init(&cache->sh->queue);
 
-    cache->cold = ngx_slab_alloc(cache->shpool, sizeof(ngx_atomic_t));
-    if (cache->cold == NULL) {
-        return NGX_ERROR;
-    }
-
-    *cache->cold = 1;
-
-    cache->size = ngx_slab_alloc(cache->shpool, sizeof(off_t));
-    if (cache->size == NULL) {
-        return NGX_ERROR;
-    }
-
-    *cache->size = 0;
+    cache->sh->cold = 1;
+    cache->sh->size = 0;
 
     cache->bsize = ngx_fs_bsize(cache->path->name.data);
 
@@ -202,7 +187,7 @@ ngx_http_file_cache_open(ngx_http_reques
         return rc;
     }
 
-    cold = *cache->cold;
+    cold = cache->sh->cold;
 
     if (rc == NGX_OK) {
 
@@ -337,7 +322,7 @@ ngx_http_file_cache_open(ngx_http_reques
             c->node->body_start = c->body_start;
             c->node->exists = 1;
 
-            *cache->size += (c->length + cache->bsize - 1) / cache->bsize;
+            cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize;
         }
 
         ngx_shmtx_unlock(&cache->shpool->mutex);
@@ -434,7 +419,7 @@ ngx_http_file_cache_exists(ngx_http_file
     ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
                NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
 
-    ngx_rbtree_insert(cache->rbtree, &fcn->node);
+    ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
 
 renew:
 
@@ -454,7 +439,7 @@ done:
 
     fcn->expire = ngx_time() + cache->inactive;
 
-    ngx_queue_insert_head(cache->queue, &fcn->queue);
+    ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
 
     c->uniq = fcn->uniq;
     c->uses = fcn->uses;
@@ -479,8 +464,8 @@ ngx_http_file_cache_lookup(ngx_http_file
 
     ngx_memcpy((u_char *) &node_key, key, sizeof(ngx_rbtree_key_t));
 
-    node = cache->rbtree->root;
-    sentinel = cache->rbtree->sentinel;
+    node = cache->sh->rbtree.root;
+    sentinel = cache->sh->rbtree.sentinel;
 
     while (node != sentinel) {
 
@@ -663,7 +648,7 @@ ngx_http_file_cache_update(ngx_http_requ
 
     c->node->length = c->length;
 
-    *cache->size += size;
+    cache->sh->size += size;
 
     if (rc == NGX_OK) {
         c->node->exists = 1;
@@ -828,8 +813,8 @@ ngx_http_file_cache_forced_expire(ngx_ht
 
     ngx_shmtx_lock(&cache->shpool->mutex);
 
-    for (q = ngx_queue_last(cache->queue);
-         q != ngx_queue_sentinel(cache->queue);
+    for (q = ngx_queue_last(&cache->sh->queue);
+         q != ngx_queue_sentinel(&cache->sh->queue);
          q = ngx_queue_prev(q))
     {
         fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
@@ -853,7 +838,7 @@ ngx_http_file_cache_forced_expire(ngx_ht
         if (!fcn->exists) {
 
             ngx_queue_remove(q);
-            ngx_rbtree_delete(cache->rbtree, &fcn->node);
+            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
             ngx_slab_free_locked(cache->shpool, fcn);
 
             break;
@@ -902,12 +887,12 @@ ngx_http_file_cache_expire(ngx_http_file
 
     for ( ;; ) {
 
-        if (ngx_queue_empty(cache->queue)) {
+        if (ngx_queue_empty(&cache->sh->queue)) {
             wait = 10;
             break;
         }
 
-        q = ngx_queue_last(cache->queue);
+        q = ngx_queue_last(&cache->sh->queue);
 
         fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
 
@@ -939,7 +924,7 @@ ngx_http_file_cache_expire(ngx_http_file
              */
 
             ngx_queue_remove(q);
-            ngx_rbtree_delete(cache->rbtree, &fcn->node);
+            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
 
             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
                        "ignore long locked inactive cache entry %*s, count:%d",
@@ -951,7 +936,7 @@ ngx_http_file_cache_expire(ngx_http_file
         if (!fcn->exists) {
 
             ngx_queue_remove(q);
-            ngx_rbtree_delete(cache->rbtree, &fcn->node);
+            ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
             ngx_slab_free_locked(cache->shpool, fcn);
 
             continue;
@@ -979,7 +964,7 @@ ngx_http_file_cache_delete(ngx_http_file
 
     fcn = ngx_queue_data(q, ngx_http_file_cache_node_t, queue);
 
-    *cache->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
+    cache->sh->size -= (fcn->length + cache->bsize - 1) / cache->bsize;
 
     path = cache->path;
 
@@ -993,7 +978,7 @@ ngx_http_file_cache_delete(ngx_http_file
 
     ngx_queue_remove(q);
 
-    ngx_rbtree_delete(cache->rbtree, &fcn->node);
+    ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node);
 
     ngx_slab_free_locked(cache->shpool, fcn);
 
@@ -1024,7 +1009,7 @@ ngx_http_file_cache_manager(void *data)
     time_t          next;
     ngx_tree_ctx_t  tree;
 
-    if (*cache->cold) {
+    if (cache->sh->cold) {
 
         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
                        "http file cache manager update");
@@ -1045,12 +1030,12 @@ ngx_http_file_cache_manager(void *data)
             return 10;
         }
 
-        *cache->cold = 0;
+        cache->sh->cold = 0;
 
         ngx_log_error(NGX_LOG_NOTICE, ngx_cycle->log, 0,
                       "http file cache: %V %.3fM, bsize: %uz",
                       &cache->path->name,
-                      ((double) *cache->size * cache->bsize) / (1024 * 1024),
+                      ((double) cache->sh->size * cache->bsize) / (1024 * 1024),
                       cache->bsize);
     }
 
@@ -1062,7 +1047,7 @@ ngx_http_file_cache_manager(void *data)
     for ( ;; ) {
         ngx_shmtx_lock(&cache->shpool->mutex);
 
-        size = *cache->size;
+        size = cache->sh->size;
 
         ngx_shmtx_unlock(&cache->shpool->mutex);
 
@@ -1245,7 +1230,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
         ngx_memcpy(fcn->key, &c->key[sizeof(ngx_rbtree_key_t)],
                    NGX_HTTP_CACHE_KEY_LEN - sizeof(ngx_rbtree_key_t));
 
-        ngx_rbtree_insert(cache->rbtree, &fcn->node);
+        ngx_rbtree_insert(&cache->sh->rbtree, &fcn->node);
 
         fcn->uses = 1;
         fcn->count = 0;
@@ -1257,7 +1242,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
         fcn->body_start = c->body_start;
         fcn->length = c->length;
 
-        *cache->size += (c->length + cache->bsize - 1) / cache->bsize;
+        cache->sh->size += (c->length + cache->bsize - 1) / cache->bsize;
 
     } else {
         ngx_queue_remove(&fcn->queue);
@@ -1265,7 +1250,7 @@ ngx_http_file_cache_add(ngx_http_file_ca
 
     fcn->expire = ngx_time() + cache->inactive;
 
-    ngx_queue_insert_head(cache->queue, &fcn->queue);
+    ngx_queue_insert_head(&cache->sh->queue, &fcn->queue);
 
     ngx_shmtx_unlock(&cache->shpool->mutex);
 
--- a/src/os/unix/ngx_shmem.h
+++ b/src/os/unix/ngx_shmem.h
@@ -13,10 +13,11 @@
 
 
 typedef struct {
-    u_char     *addr;
-    size_t      size;
-    ngx_str_t   name;
-    ngx_log_t  *log;
+    u_char      *addr;
+    size_t       size;
+    ngx_str_t    name;
+    ngx_log_t   *log;
+    ngx_uint_t   exists;   /* unsigned  exists:1;  */
 } ngx_shm_t;
 
 
--- a/src/os/win32/ngx_os.h
+++ b/src/os/win32/ngx_os.h
@@ -54,6 +54,7 @@ extern ngx_uint_t   ngx_inherited_nonblo
 extern ngx_uint_t   ngx_tcp_nodelay_and_tcp_nopush;
 extern ngx_uint_t   ngx_win32_version;
 extern ngx_fd_t     ngx_stderr_fileno;
+extern char         ngx_unique[];
 
 
 
--- a/src/os/win32/ngx_shmem.c
+++ b/src/os/win32/ngx_shmem.c
@@ -11,31 +11,50 @@
 ngx_int_t
 ngx_shm_alloc(ngx_shm_t *shm)
 {
+    u_char  *name;
+
+    name = ngx_alloc(shm->name.len + 2 + sizeof(NGX_INT32_LEN), shm->log);
+    if (name == NULL) {
+        return NGX_ERROR;
+    }
+
+    ngx_sprintf(name, "%V_%s%Z", &shm->name, ngx_unique); 
+
+    ngx_set_errno(0);
+
     shm->handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE,
-                                    0, shm->size, (char *) shm->name.data);
+                                    0, shm->size, (char *) name);
 
     if (shm->handle == NULL) {
         ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
                       "CreateFileMapping(%uz, %s) failed",
                       shm->size, shm->name.data);
-        return NGX_ERROR;
+        goto failed;
+    }
+
+    if (ngx_errno == ERROR_ALREADY_EXISTS) {
+        shm->exists = 1;
     }
 
     shm->addr = MapViewOfFile(shm->handle, FILE_MAP_WRITE, 0, 0, 0);
 
-    if (shm->addr == NULL) {
-        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
-                      "MapViewOfFile(%uz) failed", shm->size);
-
-        if (CloseHandle(shm->handle) == 0) {
-            ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
-                          "CloseHandle() failed");
-        }
-
-        return NGX_ERROR;
+    if (shm->addr != NULL) {
+        return NGX_OK;
     }
 
-    return NGX_OK;
+    ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                  "MapViewOfFile(%uz) failed", shm->size);
+
+    if (CloseHandle(shm->handle) == 0) {
+        ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
+                      "CloseHandle() failed");
+    }
+
+failed:
+
+    ngx_free(name);
+
+    return NGX_ERROR;
 }
 
 
--- a/src/os/win32/ngx_shmem.h
+++ b/src/os/win32/ngx_shmem.h
@@ -13,11 +13,12 @@
 
 
 typedef struct {
-    u_char     *addr;
-    size_t      size;
-    ngx_str_t   name;
-    HANDLE      handle;
-    ngx_log_t  *log;
+    u_char      *addr;
+    size_t       size;
+    ngx_str_t    name;
+    HANDLE       handle;
+    ngx_log_t   *log;
+    ngx_uint_t   exists;   /* unsigned  exists:1;  */
 } ngx_shm_t;
 
 
--- a/src/os/win32/ngx_win32_init.c
+++ b/src/os/win32/ngx_win32_init.c
@@ -17,6 +17,7 @@ ngx_uint_t  ngx_inherited_nonblocking = 
 ngx_uint_t  ngx_tcp_nodelay_and_tcp_nopush;
 
 ngx_fd_t    ngx_stderr_fileno;
+char        ngx_unique[NGX_INT32_LEN + 1];
 
 
 ngx_os_io_t ngx_os_io = {
@@ -60,6 +61,7 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
     DWORD        bytes;
     SOCKET       s;
     WSADATA      wsd;
+    ngx_err_t    err;
     ngx_uint_t   n;
     SYSTEM_INFO  si;
 
@@ -205,6 +207,23 @@ ngx_int_t ngx_os_init(ngx_log_t *log)
                       ngx_close_socket_n " failed");
     }
 
+    if (GetEnvironmentVariable("nginx_unique", ngx_unique, NGX_INT32_LEN + 1)
+        != 0)
+    {
+        ngx_process = NGX_PROCESS_WORKER;
+
+    } else {
+        err = ngx_errno;
+
+        if (err != ERROR_ENVVAR_NOT_FOUND) {
+            ngx_log_error(NGX_LOG_EMERG, log, err,
+                          "GetEnvironmentVariable(\"nginx_unique\") failed");
+            return NGX_ERROR;
+        }
+
+        ngx_sprintf((u_char *) ngx_unique, "%P%Z", ngx_pid);
+    }
+
     return NGX_OK;
 }