comparison src/os/win32/ngx_shmem.c @ 6133:af7eba90645d

Win32: shared memory base addresses and remapping. Two mechanisms are implemented to make it possible to store pointers in shared memory on Windows, in particular on Windows Vista and later versions with ASLR: - The ngx_shm_remap() function added to allow remapping of a shared memory zone to the address originally used for it in the master process. While important, it doesn't solve the problem by itself as in many cases it's not possible to use the address because of conflicts with other allocations. - We now create mappings at the same address in all processes by starting mappings at predefined addresses normally unused by newborn processes. These two mechanisms combined allow to use shared memory on Windows almost without problems, including reloads. Based on the patch by Sergey Brester: http://mailman.nginx.org/pipermail/nginx-devel/2015-April/006836.html
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 27 Apr 2015 18:25:42 +0300
parents b3d4e9c66e24
children
comparison
equal deleted inserted replaced
6132:859ce1c41f64 6133:af7eba90645d
7 7
8 #include <ngx_config.h> 8 #include <ngx_config.h>
9 #include <ngx_core.h> 9 #include <ngx_core.h>
10 10
11 11
12 /*
13 * Base addresses selected by system for shared memory mappings are likely
14 * to be different on Windows Vista and later versions due to address space
15 * layout randomization. This is however incompatible with storing absolute
16 * addresses within the shared memory.
17 *
18 * To make it possible to store absolute addresses we create mappings
19 * at the same address in all processes by starting mappings at predefined
20 * addresses. The addresses were selected somewhat randomly in order to
21 * minimize the probability that some other library doing something similar
22 * conflicts with us. The addresses are from the following typically free
23 * blocks:
24 *
25 * - 0x10000000 .. 0x70000000 (about 1.5 GB in total) on 32-bit platforms
26 * - 0x000000007fff0000 .. 0x000007f68e8b0000 (about 8 TB) on 64-bit platforms
27 *
28 * Additionally, we allow to change the mapping address once it was detected
29 * to be different from one originally used. This is needed to support
30 * reconfiguration.
31 */
32
33
34 #ifdef _WIN64
35 #define NGX_SHMEM_BASE 0x0000047047e00000
36 #else
37 #define NGX_SHMEM_BASE 0x2efe0000
38 #endif
39
40
41 ngx_uint_t ngx_allocation_granularity;
42
43
12 ngx_int_t 44 ngx_int_t
13 ngx_shm_alloc(ngx_shm_t *shm) 45 ngx_shm_alloc(ngx_shm_t *shm)
14 { 46 {
15 u_char *name; 47 u_char *name;
16 uint64_t size; 48 uint64_t size;
49 static u_char *base = (u_char *) NGX_SHMEM_BASE;
17 50
18 name = ngx_alloc(shm->name.len + 2 + NGX_INT32_LEN, shm->log); 51 name = ngx_alloc(shm->name.len + 2 + NGX_INT32_LEN, shm->log);
19 if (name == NULL) { 52 if (name == NULL) {
20 return NGX_ERROR; 53 return NGX_ERROR;
21 } 54 }
44 77
45 if (ngx_errno == ERROR_ALREADY_EXISTS) { 78 if (ngx_errno == ERROR_ALREADY_EXISTS) {
46 shm->exists = 1; 79 shm->exists = 1;
47 } 80 }
48 81
82 shm->addr = MapViewOfFileEx(shm->handle, FILE_MAP_WRITE, 0, 0, 0, base);
83
84 if (shm->addr != NULL) {
85 base += ngx_align(size, ngx_allocation_granularity);
86 return NGX_OK;
87 }
88
89 ngx_log_debug3(NGX_LOG_DEBUG_CORE, shm->log, ngx_errno,
90 "MapViewOfFileEx(%uz, %p) of file mapping \"%V\" failed, "
91 "retry without a base address",
92 shm->size, base, &shm->name);
93
94 /*
95 * Order of shared memory zones may be different in the master process
96 * and worker processes after reconfiguration. As a result, the above
97 * may fail due to a conflict with a previously created mapping remapped
98 * to a different address. Additionally, there may be a conflict with
99 * some other uses of the memory. In this case we retry without a base
100 * address to let the system assign the address itself.
101 */
102
49 shm->addr = MapViewOfFile(shm->handle, FILE_MAP_WRITE, 0, 0, 0); 103 shm->addr = MapViewOfFile(shm->handle, FILE_MAP_WRITE, 0, 0, 0);
50 104
51 if (shm->addr != NULL) { 105 if (shm->addr != NULL) {
52 return NGX_OK; 106 return NGX_OK;
53 } 107 }
64 118
65 return NGX_ERROR; 119 return NGX_ERROR;
66 } 120 }
67 121
68 122
123 ngx_int_t
124 ngx_shm_remap(ngx_shm_t *shm, u_char *addr)
125 {
126 if (UnmapViewOfFile(shm->addr) == 0) {
127 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
128 "UnmapViewOfFile(%p) of file mapping \"%V\" failed",
129 shm->addr, &shm->name);
130 return NGX_ERROR;
131 }
132
133 shm->addr = MapViewOfFileEx(shm->handle, FILE_MAP_WRITE, 0, 0, 0, addr);
134
135 if (shm->addr != NULL) {
136 return NGX_OK;
137 }
138
139 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,
140 "MapViewOfFileEx(%uz, %p) of file mapping \"%V\" failed",
141 shm->size, addr, &shm->name);
142
143 return NGX_ERROR;
144 }
145
146
69 void 147 void
70 ngx_shm_free(ngx_shm_t *shm) 148 ngx_shm_free(ngx_shm_t *shm)
71 { 149 {
72 if (UnmapViewOfFile(shm->addr) == 0) { 150 if (UnmapViewOfFile(shm->addr) == 0) {
73 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, 151 ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno,