Apache HTTPD
shm.c
Go to the documentation of this file.
1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements. See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_general.h"
18#include "apr_errno.h"
19#include "apr_file_io.h"
20#include "apr_shm.h"
21#include "apr_strings.h"
22#include "apr_arch_file_io.h"
23#include "limits.h"
24
29
30struct apr_shm_t {
33 void *usrmem;
37 const char *filename;
38};
39
41{
43 apr_shm_t *m = shm;
44
45 if (!UnmapViewOfFile(m->memblk)) {
46 rv = apr_get_os_error();
47 }
48 if (!CloseHandle(m->hMap)) {
49 rv = rv != APR_SUCCESS ? rv : apr_get_os_error();
50 }
51 if (m->filename) {
52 /* Remove file if file backed */
53 apr_status_t rc = apr_file_remove(m->filename, m->pool);
54 rv = rv != APR_SUCCESS ? rv : rc;
55 }
56 return rv;
57}
58
59/* See if the caller is able to create a map in the global namespace by
60 * checking if the SE_CREATE_GLOBAL_NAME privilege is enabled.
61 *
62 * Prior to APR 1.5.0, named shared memory segments were always created
63 * in the global segment. However, with recent versions of Windows this
64 * fails for unprivileged processes. Thus, with older APR, named shared
65 * memory segments can't be created by unprivileged processes on newer
66 * Windows.
67 *
68 * By checking if the caller has the privilege, shm APIs can decide
69 * whether to use the Global or Local namespace.
70 *
71 * If running on an SDK without the required API definitions *OR*
72 * some processing failure occurs trying to check the privilege, fall
73 * back to earlier behavior -- always try to use the Global namespace.
74 */
75#ifdef SE_CREATE_GLOBAL_NAME
76static int can_create_global_maps(void)
77{
82
84 if (!ok && GetLastError() == ERROR_NO_TOKEN) {
85 /* no thread-specific access token, so try to get process access token
86 */
88 }
89
90 if (ok) {
92 }
93
94 if (ok) {
95 privs.PrivilegeCount = 1;
97 privs.Privilege[0].Luid = priv_id;
98 privs.Privilege[0].Attributes = SE_PRIVILEGE_ENABLED;
100 }
101
102 if (ok && !has_priv) {
103 return 0;
104 }
105 else {
106 return 1;
107 }
108}
109#else /* SE_CREATE_GLOBAL_NAME */
110/* SDK definitions missing */
112{
113 return 1;
114}
115#endif /* SE_CREATE_GLOBAL_NAME */
116
119 const char *file,
122{
123 static apr_size_t memblock = 0;
124 HANDLE hMap, hFile;
125 apr_status_t rv;
127 apr_file_t *f;
128 void *base;
129 void *mapkey;
131
132 reqsize += sizeof(memblock_t);
133
134 if (!memblock)
135 {
138 memblock = si.dwAllocationGranularity;
139 }
140
141 /* Compute the granualar multiple of the pagesize */
142 size = memblock * (1 + (reqsize - 1) / memblock);
143 sizelo = (DWORD)size;
144#ifdef _WIN64
145 sizehi = (DWORD)(size >> 32);
146#else
147 sizehi = 0;
148#endif
149
150 if (!file) {
151 /* Do Anonymous, which must be passed as a duplicated handle */
152#ifndef _WIN32_WCE
153 hFile = INVALID_HANDLE_VALUE;
154#endif
155 mapkey = NULL;
156 }
157 else {
158 int global;
159
160 /* Do file backed, which is not an inherited handle
161 * While we could open APR_EXCL, it doesn't seem that Unix
162 * ever did. Ignore that error here, but fail later when
163 * we discover we aren't the creator of the file map object.
164 */
165 rv = apr_file_open(&f, file,
168 if ((rv != APR_SUCCESS)
169 || ((rv = apr_os_file_get(&hFile, f)) != APR_SUCCESS)) {
170 return rv;
171 }
172 rv = apr_file_trunc(f, size);
173
174 /* res_name_from_filename turns file into a pseudo-name
175 * without slashes or backslashes, and prepends the \global
176 * or \local prefix on Win2K and later
177 */
178 if (flags & APR_SHM_NS_GLOBAL) {
179 global = 1;
180 }
181 else if (flags & APR_SHM_NS_LOCAL) {
182 global = 0;
183 }
184 else {
185 global = can_create_global_maps();
186 }
188 }
189
190#if APR_HAS_UNICODE_FS
192 {
193 hMap = CreateFileMappingW(hFile, NULL, PAGE_READWRITE,
195 }
196#endif
197#if APR_HAS_ANSI_FS
199 {
200 hMap = CreateFileMappingA(hFile, NULL, PAGE_READWRITE,
202 }
203#endif
205
206 if (file) {
208 }
209
210 if (hMap && APR_STATUS_IS_EEXIST(err)) {
211 CloseHandle(hMap);
212 return APR_EEXIST;
213 }
214 if (!hMap) {
215 return err;
216 }
217
219 0, 0, size);
220 if (!base) {
221 CloseHandle(hMap);
222 return apr_get_os_error();
223 }
224
225 *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
226 (*m)->pool = pool;
227 (*m)->hMap = hMap;
228 (*m)->memblk = base;
229 (*m)->size = size;
230
231 (*m)->usrmem = (char*)base + sizeof(memblock_t);
232 (*m)->length = reqsize - sizeof(memblock_t);;
233
234 (*m)->memblk->length = (*m)->length;
235 (*m)->memblk->size = (*m)->size;
236 (*m)->filename = file ? apr_pstrdup(pool, file) : NULL;
237
238 apr_pool_cleanup_register((*m)->pool, *m,
240 return APR_SUCCESS;
241}
242
245 const char *file,
247{
248 return apr_shm_create_ex(m, reqsize, file, pool, 0);
249}
250
252{
255 return rv;
256}
257
260{
262}
263
265{
266 if (m->filename) {
267 return apr_shm_remove(m->filename, m->pool);
268 }
269 else {
270 return APR_ENOTIMPL;
271 }
272}
273
275 const char *file,
277 int global)
278{
279 HANDLE hMap;
280 void *mapkey;
281 void *base;
282
283 /* res_name_from_filename turns file into a pseudo-name
284 * without slashes or backslashes, and prepends the \global
285 * or local prefix on Win2K and later
286 */
288
289#if APR_HAS_UNICODE_FS
291 {
292#ifndef _WIN32_WCE
294#else
295 /* The WCE 3.0 lacks OpenFileMapping. So we emulate one with
296 * opening the existing shmem and reading its size from the header
297 */
299 PAGE_READWRITE, 0, sizeof(apr_shm_t), mapkey);
300#endif
301 }
302#endif
303#if APR_HAS_ANSI_FS
305 {
307 }
308#endif
309
310 if (!hMap) {
311 return apr_get_os_error();
312 }
313
315 if (!base) {
316 CloseHandle(hMap);
317 return apr_get_os_error();
318 }
319
320 *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
321 (*m)->pool = pool;
322 (*m)->memblk = base;
323 /* Real (*m)->mem->size could be recovered with VirtualQuery */
324 (*m)->size = (*m)->memblk->size;
325#if _WIN32_WCE
326 /* Reopen with real size */
328 CloseHandle(hMap);
329
331 PAGE_READWRITE, 0, (*m)->size, mapkey);
332 if (!hMap) {
333 return apr_get_os_error();
334 }
336 if (!base) {
337 CloseHandle(hMap);
338 return apr_get_os_error();
339 }
340#endif
341 (*m)->hMap = hMap;
342 (*m)->length = (*m)->memblk->length;
343 (*m)->usrmem = (char*)base + sizeof(memblock_t);
344 (*m)->filename = NULL;
345
346 apr_pool_cleanup_register((*m)->pool, *m,
348 return APR_SUCCESS;
349}
350
352 const char *file,
355{
356 apr_status_t rv;
358 int try_global_local[3] = {-1, -1, -1};
359 int cur;
360
361 if (!file) {
362 return APR_EINVAL;
363 }
364
365 if (flags & APR_SHM_NS_LOCAL) {
366 try_global_local[0] = 0; /* only search local */
367 }
368 else if (flags & APR_SHM_NS_GLOBAL) {
369 try_global_local[0] = 1; /* only search global */
370 }
371 else {
373 if (!can_create_global) { /* unprivileged process */
374 try_global_local[0] = 0; /* search local before global */
375 try_global_local[1] = 1;
376 }
377 else {
378 try_global_local[0] = 1; /* search global before local */
379 try_global_local[1] = 0;
380 }
381 }
382
383 for (cur = 0; try_global_local[cur] != -1; cur++) {
385 if (!APR_STATUS_IS_ENOENT(rv)) {
386 break;
387 }
388 }
389
390 return rv;
391}
392
394 const char *file,
396{
397 return apr_shm_attach_ex(m, file, pool, 0);
398}
399
401{
404 return rv;
405}
406
408{
409 return m->usrmem;
410}
411
413{
414 return m->length;
415}
416
418
420
422 apr_shm_t *shm)
423{
424 *osshm = shm->hMap;
425 return APR_SUCCESS;
426}
427
431{
432 void* base;
434 if (!base) {
435 return apr_get_os_error();
436 }
437
438 *m = (apr_shm_t *) apr_palloc(pool, sizeof(apr_shm_t));
439 (*m)->pool = pool;
440 (*m)->hMap = *osshm;
441 (*m)->memblk = base;
442 (*m)->usrmem = (char*)base + sizeof(memblock_t);
443 /* Real (*m)->mem->size could be recovered with VirtualQuery */
444 (*m)->size = (*m)->memblk->size;
445 (*m)->length = (*m)->memblk->length;
446 (*m)->filename = NULL;
447
448 apr_pool_cleanup_register((*m)->pool, *m,
450 return APR_SUCCESS;
451}
452
#define TRUE
Definition abts.h:38
#define FALSE
Definition abts.h:35
#define CreateFileMappingW(fh, sd, d1, d2, d3, nm)
#define OpenFileMappingW(d, b, nm)
#define OpenFileMappingA(d, b, nm)
#define GetCurrentProcess()
#define CreateFileMappingA(fh, sd, d1, d2, d3, nm)
#define GetCurrentThread()
#define CloseHandle(h)
APR Error Codes.
APR File I/O Handling.
APR Miscellaneous library routines.
APR Shared Memory Routines.
APR Strings library.
ap_conf_vector_t * base
#define APR_ENOTIMPL
Definition apr_errno.h:476
#define APR_EINVAL
Definition apr_errno.h:711
#define APR_EEXIST
Definition apr_errno.h:648
#define APR_STATUS_IS_EEXIST(s)
Definition apr_errno.h:1233
#define APR_STATUS_IS_ENOENT(s)
Definition apr_errno.h:1246
apr_file_t * f
const char apr_ssize_t int flags
Definition apr_encode.h:168
apr_redis_t * rc
Definition apr_redis.h:173
#define BOOL
Definition ssl_private.h:81
const void apr_status_t(*) apr_status_t(* APR_DECLARE)(void) apr_pool_pre_cleanup_register(apr_pool_t *p
Definition apr_pools.h:646
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
#define apr_get_os_error()
Definition apr_errno.h:1217
int apr_status_t
Definition apr_errno.h:44
const char apr_file_t * file
#define APR_READ
Definition apr_file_io.h:93
#define APR_BINARY
Definition apr_file_io.h:98
#define APR_WRITE
Definition apr_file_io.h:94
#define APR_CREATE
Definition apr_file_io.h:95
#define APR_UWRITE
#define APR_UREAD
#define APR_PERMS_SET_ENOTIMPL(type)
#define APR_POOL_IMPLEMENT_ACCESSOR(type)
Definition apr_pools.h:91
void * apr_os_shm_t
apr_os_shm_t * osshm
apr_shm_t * shm
#define APR_SHM_NS_GLOBAL
Definition apr_shm.h:79
apr_size_t const char * filename
Definition apr_shm.h:72
#define APR_SHM_NS_LOCAL
Definition apr_shm.h:78
apr_size_t reqsize
Definition apr_shm.h:71
const void * m
apr_int32_t apr_int32_t apr_int32_t err
return NULL
Definition mod_so.c:359
memblock_t * memblk
Definition shm.c:32
void * usrmem
Definition shm.c:33
apr_pool_t * pool
apr_size_t length
Definition shm.c:35
const char * filename
HANDLE hMap
Definition shm.c:36
apr_size_t size
Definition shm.c:34
apr_size_t length
Definition shm.c:27
apr_size_t size
Definition shm.c:26
apr_status_t apr_file_trunc(apr_file_t *fp, apr_off_t offset)
Definition seek.c:99
#define ELSE_WIN_OS_IS_ANSI
typedef HANDLE(WINAPI *apr_winapi_fpt_CreateToolhelp32Snapshot)(DWORD dwFlags
#define IF_WIN_OS_IS_UNICODE
typedef DWORD(WINAPI *apr_winapi_fpt_GetCompressedFileSizeA)(IN LPCSTR lpFileName
void * res_name_from_filename(const char *file, int global, apr_pool_t *pool)
Definition open.c:140
static apr_status_t shm_cleanup(void *shm)
Definition shm.c:40
static apr_status_t shm_attach_internal(apr_shm_t **m, const char *file, apr_pool_t *pool, int global)
Definition shm.c:274
static int can_create_global_maps(void)
Definition shm.c:111