1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 /***************************************************************************
19 * Description: Shared Memory support *
20 * Author: Mladen Turk <mturk@jboss.com> *
21 * Author: Rainer Jung <rjung@apache.org> *
22 ***************************************************************************/
23
24 #include "jk_global.h"
25 #include "jk_pool.h"
26 #include "jk_util.h"
27 #include "jk_mt.h"
28 #include "jk_lb_worker.h"
29 #include "jk_ajp13_worker.h"
30 #include "jk_ajp14_worker.h"
31 #include "jk_shm.h"
32
33 /** jk shm header core data structure
34 * This is always the first slot in shared memory.
35 */
36 struct jk_shm_header_data
37 {
38 /* Shared memory magic JK_SHM_MAGIC */
39 char magic[JK_SHM_MAGIC_SIZ];
40 unsigned int size;
41 unsigned int pos;
42 unsigned int childs;
43 unsigned int workers;
44 unsigned int maintain_checking;
45 volatile time_t maintain_time;
46 };
47
48 typedef struct jk_shm_header_data jk_shm_header_data_t;
49
50 /** jk shm header record structure
51 */
52 struct jk_shm_header
53 {
54 union {
55 jk_shm_header_data_t data;
56 char alignbuf[JK_SHM_SLOT_SIZE];
57 } h;
58 char buf[1];
59 };
60
61 typedef struct jk_shm_header jk_shm_header_t;
62
63 /** jk shm in memory structure.
64 */
65 struct jk_shm
66 {
67 unsigned int size;
68 unsigned int ajp_workers;
69 unsigned int lb_sub_workers;
70 unsigned int lb_workers;
71 char *filename;
72 char *lockname;
73 int fd;
74 int fd_lock;
75 int attached;
76 jk_shm_header_t *hdr;
77 JK_CRIT_SEC cs;
78 };
79
80 typedef struct jk_shm jk_shm_t;
81
82 static const char shm_signature[] = { JK_SHM_MAGIC };
83 static jk_shm_t jk_shmem = { 0, 0, 0, 0, NULL, NULL, -1, -1, 0, NULL};
84 #if defined (WIN32)
85 static HANDLE jk_shm_map = NULL;
86 static HANDLE jk_shm_hlock = NULL;
87 #endif
88 static int jk_shm_inited_cs = 0;
89
jk_shm_calculate_slot_size()90 static size_t jk_shm_calculate_slot_size()
91 {
92 int align = 64;
93 size_t slot_size = 0;
94 size_t this_size = 0;
95
96 this_size = sizeof(jk_shm_header_data_t);
97 if (this_size > slot_size)
98 slot_size = this_size;
99
100 this_size = sizeof(jk_shm_worker_header_t);
101 if (this_size > slot_size)
102 slot_size = this_size;
103
104 this_size = sizeof(jk_shm_ajp_worker_t);
105 if (this_size > slot_size)
106 slot_size = this_size;
107
108 this_size = sizeof(jk_shm_lb_sub_worker_t);
109 if (this_size > slot_size)
110 slot_size = this_size;
111
112 this_size = sizeof(jk_shm_lb_worker_t);
113 if (this_size > slot_size)
114 slot_size = this_size;
115
116 slot_size = JK_ALIGN(slot_size, align);
117 return slot_size;
118 }
119
120 /* Calculate needed shm size */
jk_shm_calculate_size(jk_map_t * init_data,jk_logger_t * l)121 int jk_shm_calculate_size(jk_map_t *init_data, jk_logger_t *l)
122 {
123 char **worker_list;
124 size_t needed_slot_size = 0;
125 unsigned int i;
126 unsigned int num_of_workers;
127 int num_of_ajp_workers = 0;
128 int num_of_lb_sub_workers = 0;
129 int num_of_lb_workers = 0;
130
131 JK_TRACE_ENTER(l);
132
133 if (jk_get_worker_list(init_data, &worker_list,
134 &num_of_workers) == JK_FALSE) {
135 jk_log(l, JK_LOG_ERROR,
136 "Could not get worker list from map");
137 JK_TRACE_EXIT(l);
138 return 0;
139 }
140 needed_slot_size = jk_shm_calculate_slot_size();
141 if (JK_IS_DEBUG_LEVEL(l))
142 jk_log(l, JK_LOG_DEBUG, "JK_SHM_SLOT_SIZE defined as %d, need at least %d",
143 JK_SHM_SLOT_SIZE , needed_slot_size);
144 if (needed_slot_size > JK_SHM_SLOT_SIZE) {
145 jk_log(l, JK_LOG_ERROR,
146 "JK_SHM_SLOT_SIZE %d is too small, need at least %d",
147 JK_SHM_SLOT_SIZE, needed_slot_size);
148 JK_TRACE_EXIT(l);
149 return 0;
150 }
151 for (i = 0; i < num_of_workers; i++) {
152 const char *type = jk_get_worker_type(init_data, worker_list[i]);
153
154 if (!strcmp(type, JK_AJP13_WORKER_NAME) ||
155 !strcmp(type, JK_AJP14_WORKER_NAME)) {
156 num_of_ajp_workers++;
157 }
158 else if (!strcmp(type, JK_LB_WORKER_NAME)) {
159 char **member_list;
160 unsigned int num_of_members;
161 num_of_lb_workers++;
162 if (jk_get_lb_worker_list(init_data, worker_list[i],
163 &member_list, &num_of_members) == JK_FALSE) {
164 jk_log(l, JK_LOG_ERROR,
165 "Could not get member list for lb worker from map");
166 }
167 else {
168 if (JK_IS_DEBUG_LEVEL(l))
169 jk_log(l, JK_LOG_DEBUG, "worker %s of type %s has %u members",
170 worker_list[i], JK_LB_WORKER_NAME, num_of_members);
171 num_of_lb_sub_workers += num_of_members;
172 }
173 }
174 }
175 if (JK_IS_DEBUG_LEVEL(l))
176 jk_log(l, JK_LOG_DEBUG, "shared memory will contain %d ajp workers and %d lb workers with %d members",
177 num_of_ajp_workers,
178 num_of_lb_workers,
179 num_of_lb_sub_workers);
180 jk_shmem.ajp_workers = num_of_ajp_workers;
181 jk_shmem.lb_sub_workers = num_of_lb_sub_workers;
182 jk_shmem.lb_workers = num_of_lb_workers;
183 JK_TRACE_EXIT(l);
184 return (JK_SHM_SLOT_SIZE * (jk_shmem.ajp_workers +
185 jk_shmem.lb_sub_workers * 2 +
186 jk_shmem.lb_workers));
187 }
188
189
190 #if defined (WIN32)
191
192 /* Use plain memory */
jk_shm_open(const char * fname,int sz,jk_logger_t * l)193 int jk_shm_open(const char *fname, int sz, jk_logger_t *l)
194 {
195 int rc = -1;
196 int attached = 0;
197 char lkname[MAX_PATH];
198 char shname[MAX_PATH] = "";
199
200 JK_TRACE_ENTER(l);
201 if (!jk_shm_inited_cs) {
202 jk_shm_inited_cs = 1;
203 JK_INIT_CS(&jk_shmem.cs, rc);
204 }
205 JK_ENTER_CS(&jk_shmem.cs);
206 if (jk_shmem.hdr) {
207 if (JK_IS_DEBUG_LEVEL(l))
208 jk_log(l, JK_LOG_DEBUG, "Shared memory is already opened");
209 JK_TRACE_EXIT(l);
210 JK_LEAVE_CS(&jk_shmem.cs);
211 return 0;
212 }
213 if (sz < 0) {
214 jk_log(l, JK_LOG_ERROR, "Invalid shared memory size (%d)", sz);
215 JK_TRACE_EXIT(l);
216 return EINVAL;
217 }
218 jk_shmem.size = JK_SHM_ALIGN(JK_SHM_SLOT_SIZE + sz);
219 #if defined (WIN32)
220 jk_shm_map = NULL;
221 jk_shm_hlock = NULL;
222 if (fname) {
223 int i;
224 SIZE_T shmsz = 0;
225 strcpy(shname, "Local\\");
226 strncat(shname, fname, MAX_PATH - 8);
227 for(i = 7; i < (int)strlen(shname); i++) {
228 if (!jk_isalnum(shname[i]))
229 shname[i] = '_';
230 else
231 shname[i] = toupper(shname[i]);
232 }
233 strcpy(lkname, shname);
234 strncat(lkname, "_MUTEX", MAX_PATH - 1);
235 jk_shm_hlock = CreateMutex(jk_get_sa_with_null_dacl(), TRUE, lkname);
236 if (jk_shm_hlock == NULL) {
237 if (GetLastError() == ERROR_ALREADY_EXISTS) {
238 attached = 1;
239 jk_shm_hlock = OpenMutex(MUTEX_ALL_ACCESS, FALSE, lkname);
240 }
241 }
242 else if (GetLastError() == ERROR_ALREADY_EXISTS)
243 attached = 1;
244 if (jk_shm_hlock == NULL) {
245 rc = GetLastError();
246 jk_log(l, JK_LOG_ERROR, "Failed to open shared memory mutex %s with errno=%d",
247 lkname, rc);
248 JK_LEAVE_CS(&jk_shmem.cs);
249 JK_TRACE_EXIT(l);
250 return rc;
251 }
252 if (attached) {
253 DWORD ws = WaitForSingleObject(jk_shm_hlock, INFINITE);
254 if (ws == WAIT_FAILED) {
255 rc = GetLastError();
256 CloseHandle(jk_shm_hlock);
257 jk_shm_hlock = NULL;
258 JK_LEAVE_CS(&jk_shmem.cs);
259 JK_TRACE_EXIT(l);
260 return rc;
261 }
262 jk_shm_map = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, shname);
263 if (jk_shm_map == NULL) {
264 rc = GetLastError();
265 jk_log(l, JK_LOG_ERROR, "Failed to open shared memory %s with errno=%d",
266 shname, rc);
267 }
268 }
269 if (jk_shm_map == NULL) {
270 shmsz = jk_shmem.size;
271 jk_shm_map = CreateFileMapping(INVALID_HANDLE_VALUE,
272 jk_get_sa_with_null_dacl(),
273 PAGE_READWRITE,
274 0,
275 (DWORD)shmsz,
276 shname);
277 }
278 if (jk_shm_map == NULL || jk_shm_map == INVALID_HANDLE_VALUE) {
279 rc = GetLastError();
280 jk_log(l, JK_LOG_ERROR, "Failed to map shared memory %s with errno=%d",
281 fname, rc);
282 CloseHandle(jk_shm_hlock);
283 jk_shm_hlock = NULL;
284 jk_shm_map = NULL;
285 JK_LEAVE_CS(&jk_shmem.cs);
286 JK_TRACE_EXIT(l);
287 return rc;
288 }
289 jk_shmem.hdr = (jk_shm_header_t *)MapViewOfFile(jk_shm_map,
290 FILE_MAP_READ | FILE_MAP_WRITE,
291 0,
292 0,
293 shmsz);
294 }
295 else
296 #endif
297 jk_shmem.hdr = (jk_shm_header_t *)calloc(1, jk_shmem.size);
298 if (!jk_shmem.hdr) {
299 #if defined (WIN32)
300 rc = GetLastError();
301 if (jk_shm_map) {
302 CloseHandle(jk_shm_map);
303 jk_shm_map = NULL;
304 }
305 if (jk_shm_hlock) {
306 CloseHandle(jk_shm_hlock);
307 jk_shm_hlock = NULL;
308 }
309 #endif
310 JK_LEAVE_CS(&jk_shmem.cs);
311 JK_TRACE_EXIT(l);
312 return rc;
313 }
314 if (!jk_shmem.filename) {
315 if (shname[0])
316 jk_shmem.filename = strdup(shname);
317 else
318 jk_shmem.filename = strdup("memory");
319 }
320 jk_shmem.fd = 0;
321 jk_shmem.attached = attached;
322 if (!attached) {
323 memset(jk_shmem.hdr, 0, jk_shmem.size);
324 memcpy(jk_shmem.hdr->h.data.magic, shm_signature,
325 JK_SHM_MAGIC_SIZ);
326 jk_shmem.hdr->h.data.size = sz;
327 jk_shmem.hdr->h.data.childs = 1;
328 jk_shmem.hdr->h.data.maintain_checking = 0;
329 jk_shmem.hdr->h.data.maintain_time = time(NULL);
330 }
331 else {
332 jk_shmem.hdr->h.data.childs++;
333 /*
334 * Reset the shared memory so that
335 * alloc works even for attached memory.
336 * XXX: This might break already used memory
337 * if the number of workers change between
338 * open and attach or between two attach operations.
339 */
340 #if 0
341 if (jk_shmem.hdr->h.data.childs > 1) {
342 if (JK_IS_DEBUG_LEVEL(l)) {
343 jk_log(l, JK_LOG_DEBUG,
344 "Resetting the shared memory for child %d",
345 jk_shmem.hdr->h.data.childs);
346 }
347 }
348 jk_shmem.hdr->h.data.pos = 0;
349 jk_shmem.hdr->h.data.workers = 0;
350 #endif
351 }
352 #if defined (WIN32)
353 if (jk_shm_hlock != NULL) {
354 /* Unlock shared memory */
355 ReleaseMutex(jk_shm_hlock);
356 }
357 #endif
358 JK_LEAVE_CS(&jk_shmem.cs);
359 if (JK_IS_DEBUG_LEVEL(l))
360 jk_log(l, JK_LOG_DEBUG,
361 "%s shared memory %s [%d] size=%u workers=%d free=%u addr=%#lx",
362 attached ? "Attached" : "Initialized",
363 jk_shm_name(),
364 jk_shmem.hdr->h.data.childs,
365 jk_shmem.size, jk_shmem.hdr->h.data.workers - 1,
366 jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
367 jk_shmem.hdr);
368 JK_TRACE_EXIT(l);
369 return 0;
370 }
371
jk_shm_attach(const char * fname,int sz,jk_logger_t * l)372 int jk_shm_attach(const char *fname, int sz, jk_logger_t *l)
373 {
374 JK_TRACE_ENTER(l);
375 if (!jk_shm_open(fname, sz, l)) {
376 if (!jk_shmem.attached) {
377 jk_shmem.attached = 1;
378 if (JK_IS_DEBUG_LEVEL(l)) {
379 jk_log(l, JK_LOG_DEBUG,
380 "Attached shared memory %s [%d] size=%u free=%u addr=%#lx",
381 jk_shm_name(), jk_shmem.hdr->h.data.childs, jk_shmem.size,
382 jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
383 jk_shmem.hdr);
384 }
385 }
386 JK_TRACE_EXIT(l);
387 return 0;
388 }
389 else {
390 JK_TRACE_EXIT(l);
391 return -1;
392 }
393 }
394
jk_shm_close(jk_logger_t * l)395 void jk_shm_close(jk_logger_t *l)
396 {
397 if (jk_shm_inited_cs) {
398 JK_ENTER_CS(&jk_shmem.cs);
399 }
400 if (jk_shmem.hdr) {
401 if (JK_IS_DEBUG_LEVEL(l)) {
402 jk_log(l, JK_LOG_DEBUG,
403 "Closed shared memory %s childs=%u",
404 jk_shm_name(), jk_shmem.hdr->h.data.childs);
405 }
406 #if defined (WIN32)
407 if (jk_shm_hlock) {
408 WaitForSingleObject(jk_shm_hlock, 60000);
409 ReleaseMutex(jk_shm_hlock);
410 CloseHandle(jk_shm_hlock);
411 jk_shm_hlock = NULL;
412 }
413 if (jk_shm_map) {
414 --jk_shmem.hdr->h.data.childs;
415 UnmapViewOfFile(jk_shmem.hdr);
416 CloseHandle(jk_shm_map);
417 jk_shm_map = NULL;
418 }
419 else
420 #endif
421 free(jk_shmem.hdr);
422 }
423 jk_shmem.hdr = NULL;
424 if (jk_shmem.filename) {
425 free(jk_shmem.filename);
426 jk_shmem.filename = NULL;
427 }
428 if (jk_shm_inited_cs) {
429 JK_LEAVE_CS(&jk_shmem.cs);
430 }
431 }
432
433 #else
434
435 #include <unistd.h>
436 #include <fcntl.h>
437 #include <errno.h>
438 #include <sys/stat.h>
439 #include <sys/mman.h>
440 #include <sys/uio.h>
441
442 #ifndef MAP_FAILED
443 #define MAP_FAILED (-1)
444 #endif
445
446 #ifndef MAP_FILE
447 #define MAP_FILE (0)
448 #endif
449
do_shm_open_lock(const char * fname,int attached,jk_logger_t * l)450 static int do_shm_open_lock(const char *fname, int attached, jk_logger_t *l)
451 {
452 int rc;
453 char flkname[256];
454 #ifdef AS400_UTF8
455 char *wptr;
456 #endif
457
458 JK_TRACE_ENTER(l);
459
460 if (attached && jk_shmem.lockname) {
461 #ifdef JK_SHM_LOCK_REOPEN
462 jk_shmem.fd_lock = open(jk_shmem.lockname, O_RDWR, 0666);
463 #else
464 errno = EINVAL;
465 #endif
466 if (jk_shmem.fd_lock == -1) {
467 rc = errno;
468 JK_TRACE_EXIT(l);
469 return rc;
470 }
471 if (JK_IS_DEBUG_LEVEL(l))
472 jk_log(l, JK_LOG_DEBUG,
473 "Duplicated shared memory lock %s", jk_shmem.lockname);
474 JK_TRACE_EXIT(l);
475 return 0;
476 }
477
478 if (!jk_shmem.lockname) {
479 #ifdef JK_SHM_LOCK_REOPEN
480 int i;
481 jk_shmem.fd_lock = -1;
482 mode_t mask = umask(0);
483 for (i = 0; i < 8; i++) {
484 strcpy(flkname, "/tmp/jkshmlock.XXXXXX");
485 if (mktemp(flkname)) {
486 jk_shmem.fd_lock = open(flkname, O_RDWR|O_CREAT|O_TRUNC, 0666);
487 if (jk_shmem.fd_lock >= 0)
488 break;
489 }
490 }
491 umask(mask);
492 #else
493 strcpy(flkname, fname);
494 strcat(flkname, ".lock");
495 #ifdef AS400_UTF8
496 wptr = (char *)malloc(strlen(flkname) + 1);
497 jk_ascii2ebcdic((char *)flkname, wptr);
498 jk_shmem.fd_lock = open(wptr, O_RDWR|O_CREAT|O_TRUNC, 0666);
499 free(wptr);
500 #else
501 jk_shmem.fd_lock = open(flkname, O_RDWR|O_CREAT|O_TRUNC, 0666);
502 #endif
503 #endif
504 if (jk_shmem.fd_lock == -1) {
505 rc = errno;
506 JK_TRACE_EXIT(l);
507 return rc;
508 }
509 jk_shmem.lockname = strdup(flkname);
510 }
511 else {
512 /* Nothing to do */
513 JK_TRACE_EXIT(l);
514 return 0;
515 }
516
517 if (ftruncate(jk_shmem.fd_lock, 1)) {
518 rc = errno;
519 close(jk_shmem.fd_lock);
520 jk_shmem.fd_lock = -1;
521 JK_TRACE_EXIT(l);
522 return rc;
523 }
524 if (lseek(jk_shmem.fd_lock, 0, SEEK_SET) != 0) {
525 rc = errno;
526 close(jk_shmem.fd_lock);
527 jk_shmem.fd_lock = -1;
528 return rc;
529 }
530 if (JK_IS_DEBUG_LEVEL(l))
531 jk_log(l, JK_LOG_DEBUG,
532 "Opened shared memory lock %s", jk_shmem.lockname);
533 JK_TRACE_EXIT(l);
534 return 0;
535 }
536
do_shm_open(const char * fname,int attached,int sz,jk_logger_t * l)537 static int do_shm_open(const char *fname, int attached,
538 int sz, jk_logger_t *l)
539 {
540 int rc;
541 int fd;
542 void *base;
543 #ifdef AS400_UTF8
544 char *wptr;
545 #endif
546
547 JK_TRACE_ENTER(l);
548 if (!jk_shm_inited_cs) {
549 jk_shm_inited_cs = 1;
550 JK_INIT_CS(&jk_shmem.cs, rc);
551 }
552 if (jk_shmem.hdr) {
553 /* Probably a call from vhost */
554 if (!attached)
555 attached = 1;
556 }
557 else if (attached) {
558 /* We should already have a header
559 * Use memory if we don't
560 */
561 JK_TRACE_EXIT(l);
562 return 0;
563 }
564 if (sz < 0) {
565 jk_log(l, JK_LOG_ERROR, "Invalid shared memory size (%d)", sz);
566 JK_TRACE_EXIT(l);
567 return EINVAL;
568 }
569 jk_shmem.size = JK_SHM_ALIGN(JK_SHM_SLOT_SIZE + sz);
570
571 if (!fname) {
572 /* Use plain memory in case there is no file name */
573 if (!jk_shmem.filename)
574 jk_shmem.filename = strdup("memory");
575 if (JK_IS_DEBUG_LEVEL(l))
576 jk_log(l, JK_LOG_DEBUG,
577 "Using process memory as shared memory");
578 JK_TRACE_EXIT(l);
579 return 0;
580 }
581
582 if (!jk_shmem.filename) {
583 jk_shmem.filename = (char *)malloc(strlen(fname) + 32);
584 sprintf(jk_shmem.filename, "%s.%" JK_PID_T_FMT, fname, getpid());
585 }
586 if (!attached) {
587 size_t size;
588 jk_shmem.attached = 0;
589 #ifdef AS400_UTF8
590 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
591 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
592 fd = open(wptr, O_RDWR|O_CREAT|O_TRUNC, 0666);
593 free(wptr);
594 #else
595 fd = open(jk_shmem.filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
596 #endif
597 if (fd == -1) {
598 jk_shmem.size = 0;
599 JK_TRACE_EXIT(l);
600 return errno;
601 }
602 size = lseek(fd, 0, SEEK_END);
603 if (size < jk_shmem.size) {
604 size = jk_shmem.size;
605 if (ftruncate(fd, jk_shmem.size)) {
606 rc = errno;
607 close(fd);
608 #ifdef AS400_UTF8
609 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
610 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
611 unlink(wptr);
612 free(wptr);
613 #else
614 unlink(jk_shmem.filename);
615 #endif
616 jk_shmem.size = 0;
617 JK_TRACE_EXIT(l);
618 return rc;
619 }
620 if (JK_IS_DEBUG_LEVEL(l))
621 jk_log(l, JK_LOG_DEBUG,
622 "Truncated shared memory to %u", size);
623 }
624 if (lseek(fd, 0, SEEK_SET) != 0) {
625 rc = errno;
626 close(fd);
627 #ifdef AS400_UTF8
628 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
629 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
630 unlink(wptr);
631 free(wptr);
632 #else
633 unlink(jk_shmem.filename);
634 #endif
635 jk_shmem.size = 0;
636 JK_TRACE_EXIT(l);
637 return rc;
638 }
639
640 base = mmap((caddr_t)0, jk_shmem.size,
641 PROT_READ | PROT_WRITE,
642 MAP_FILE | MAP_SHARED,
643 fd, 0);
644 if (base == (caddr_t)MAP_FAILED || base == (caddr_t)0) {
645 rc = errno;
646 close(fd);
647 #ifdef AS400_UTF8
648 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
649 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
650 unlink(wptr);
651 free(wptr);
652 #else
653 unlink(jk_shmem.filename);
654 #endif
655 jk_shmem.size = 0;
656 JK_TRACE_EXIT(l);
657 return rc;
658 }
659 jk_shmem.hdr = base;
660 jk_shmem.fd = fd;
661 memset(jk_shmem.hdr, 0, jk_shmem.size);
662 memcpy(jk_shmem.hdr->h.data.magic, shm_signature, JK_SHM_MAGIC_SIZ);
663 jk_shmem.hdr->h.data.size = sz;
664 jk_shmem.hdr->h.data.childs = 1;
665 jk_shmem.hdr->h.data.maintain_checking = 0;
666 jk_shmem.hdr->h.data.maintain_time = time(NULL);
667 if (JK_IS_DEBUG_LEVEL(l))
668 jk_log(l, JK_LOG_DEBUG,
669 "Initialized shared memory %s size=%u free=%u addr=%#lx",
670 jk_shm_name(), jk_shmem.size,
671 jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
672 jk_shmem.hdr);
673 }
674 else {
675 jk_shmem.hdr->h.data.childs++;
676 jk_shmem.attached = (int)getpid();
677 if (JK_IS_DEBUG_LEVEL(l))
678 jk_log(l, JK_LOG_DEBUG,
679 "Attached shared memory %s [%d] size=%u workers=%u free=%u addr=%#lx",
680 jk_shm_name(),
681 jk_shmem.hdr->h.data.childs,
682 jk_shmem.size, jk_shmem.hdr->h.data.workers - 1,
683 jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
684 jk_shmem.hdr);
685 #if 0
686 /*
687 * Reset the shared memory so that
688 * alloc works even for attached memory.
689 * XXX: This might break already used memory
690 * if the number of workers change between
691 * open and attach or between two attach operations.
692 */
693 if (nchild > 1) {
694 if (JK_IS_DEBUG_LEVEL(l)) {
695 jk_log(l, JK_LOG_DEBUG,
696 "Resetting the shared memory for child %d",
697 nchild);
698 }
699 }
700 jk_shmem.hdr->h.data.pos = 0;
701 jk_shmem.hdr->h.data.workers = 0;
702 #endif
703 }
704 if ((rc = do_shm_open_lock(jk_shmem.filename, attached, l))) {
705 if (!attached) {
706 munmap((void *)jk_shmem.hdr, jk_shmem.size);
707 close(jk_shmem.fd);
708 #ifdef AS400_UTF8
709 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
710 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
711 unlink(wptr);
712 free(wptr);
713 #else
714 unlink(jk_shmem.filename);
715 #endif
716 }
717 jk_shmem.hdr = NULL;
718 jk_shmem.fd = -1;
719 JK_TRACE_EXIT(l);
720 return rc;
721 }
722 JK_TRACE_EXIT(l);
723 return 0;
724 }
725
jk_shm_open(const char * fname,int sz,jk_logger_t * l)726 int jk_shm_open(const char *fname, int sz, jk_logger_t *l)
727 {
728 return do_shm_open(fname, 0, sz, l);
729 }
730
jk_shm_attach(const char * fname,int sz,jk_logger_t * l)731 int jk_shm_attach(const char *fname, int sz, jk_logger_t *l)
732 {
733 return do_shm_open(fname, 1, sz, l);
734 }
735
jk_shm_close(jk_logger_t * l)736 void jk_shm_close(jk_logger_t *l)
737 {
738 #ifdef AS400_UTF8
739 char *wptr;
740 #endif
741
742 if (jk_shmem.hdr) {
743 if (JK_IS_DEBUG_LEVEL(l)) {
744 jk_log(l, JK_LOG_DEBUG,
745 "Closed shared memory %s childs=%u",
746 jk_shm_name(), jk_shmem.hdr->h.data.childs);
747 }
748 --jk_shmem.hdr->h.data.childs;
749
750 #ifdef JK_SHM_LOCK_REOPEN
751 if (jk_shmem.fd_lock >= 0) {
752 close(jk_shmem.fd_lock);
753 jk_shmem.fd_lock = -1;
754 }
755 #endif
756 if (jk_shmem.attached) {
757 int p = (int)getpid();
758 if (p == jk_shmem.attached) {
759 /* In case this is a forked child
760 * do not close the shared memory.
761 * It will be closed by the parent.
762 */
763 jk_shmem.size = 0;
764 jk_shmem.hdr = NULL;
765 jk_shmem.fd = -1;
766 return;
767 }
768 }
769 if (jk_shmem.fd >= 0) {
770 munmap((void *)jk_shmem.hdr, jk_shmem.size);
771 close(jk_shmem.fd);
772 }
773 if (jk_shmem.fd_lock >= 0)
774 close(jk_shmem.fd_lock);
775 if (jk_shmem.lockname) {
776 #ifdef AS400_UTF8
777 wptr = (char *)malloc(strlen(jk_shmem.lockname) + 1);
778 jk_ascii2ebcdic((char *)jk_shmem.lockname, wptr);
779 unlink(wptr);
780 free(wptr);
781 #else
782 unlink(jk_shmem.lockname);
783 #endif
784 free(jk_shmem.lockname);
785 jk_shmem.lockname = NULL;
786 }
787 if (jk_shmem.filename) {
788 #ifdef AS400_UTF8
789 wptr = (char *)malloc(strlen(jk_shmem.filename) + 1);
790 jk_ascii2ebcdic((char *)jk_shmem.filename, wptr);
791 unlink(wptr);
792 free(wptr);
793 #else
794 unlink(jk_shmem.filename);
795 #endif
796 free(jk_shmem.filename);
797 jk_shmem.filename = NULL;
798 }
799 }
800 jk_shmem.size = 0;
801 jk_shmem.hdr = NULL;
802 jk_shmem.fd = -1;
803 jk_shmem.fd_lock = -1;
804 }
805
806
807 #endif
808
jk_shm_alloc_worker(jk_pool_t * p,int type,int parent_id,const char * name,jk_logger_t * l)809 jk_shm_worker_header_t *jk_shm_alloc_worker(jk_pool_t *p, int type,
810 int parent_id, const char *name,
811 jk_logger_t *l)
812 {
813 unsigned int i;
814 jk_shm_worker_header_t *w = 0;
815
816 if (jk_check_attribute_length("name", name, l) == JK_FALSE) {
817 return NULL;
818 }
819
820 if (jk_shmem.hdr) {
821 jk_shm_lock();
822 for (i = 0; i < jk_shmem.hdr->h.data.pos; i += JK_SHM_SLOT_SIZE) {
823 w = (jk_shm_worker_header_t *)(jk_shmem.hdr->buf + i);
824 if (w->type == type && w-> parent_id == parent_id &&
825 strcmp(w->name, name) == 0) {
826 /* We have found already created worker */
827 jk_shm_unlock();
828 return w;
829 }
830 }
831 /* Allocate new worker */
832 if ((jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos) >= JK_SHM_SLOT_SIZE) {
833 w = (jk_shm_worker_header_t *)(jk_shmem.hdr->buf + jk_shmem.hdr->h.data.pos);
834 memset(w, 0, JK_SHM_SLOT_SIZE);
835 strncpy(w->name, name, JK_SHM_STR_SIZ);
836 jk_shmem.hdr->h.data.workers++;
837 w->id = jk_shmem.hdr->h.data.workers;
838 w->type = type;
839 w->parent_id = parent_id;
840 jk_shmem.hdr->h.data.pos += JK_SHM_SLOT_SIZE;
841 }
842 else {
843 /* No more free memory left.
844 */
845 jk_log(l, JK_LOG_ERROR,
846 "Could not allocate shared memory for worker %s",
847 name);
848 w = NULL;
849 }
850 jk_shm_unlock();
851 }
852 else if (p) {
853 w = (jk_shm_worker_header_t *)jk_pool_alloc(p, JK_SHM_SLOT_SIZE);
854 if (w) {
855 memset(w, 0, JK_SHM_SLOT_SIZE);
856 strncpy(w->name, name, JK_SHM_STR_SIZ);
857 w->id = 0;
858 w->type = type;
859 w->parent_id = parent_id;
860 }
861 }
862
863 return w;
864 }
865
jk_shm_name()866 const char *jk_shm_name()
867 {
868 return jk_shmem.filename;
869 }
870
jk_shm_check_maintain(time_t trigger)871 int jk_shm_check_maintain(time_t trigger)
872 {
873 int rv = JK_FALSE;
874 int maintain_checking = JK_ATOMIC_INCREMENT(&(jk_shmem.hdr->h.data.maintain_checking));
875 /* Another process (or thread) is already checking */
876 if (maintain_checking > 1) {
877 JK_ATOMIC_DECREMENT(&(jk_shmem.hdr->h.data.maintain_checking));
878 return rv;
879 }
880 if (jk_shmem.hdr->h.data.maintain_time <= trigger) {
881 jk_shmem.hdr->h.data.maintain_time = time(NULL);
882 rv = JK_TRUE;
883 }
884 JK_ATOMIC_DECREMENT(&(jk_shmem.hdr->h.data.maintain_checking));
885 return rv;
886 }
887
jk_shm_lock()888 int jk_shm_lock()
889 {
890 int rc = JK_TRUE;
891
892 if (!jk_shm_inited_cs)
893 return JK_FALSE;
894 JK_ENTER_CS(&jk_shmem.cs);
895 #if defined (WIN32)
896 if (jk_shm_hlock != NULL) {
897 if (WaitForSingleObject(jk_shm_hlock, INFINITE) == WAIT_FAILED)
898 rc = JK_FALSE;
899 }
900 #else
901 if (jk_shmem.fd_lock != -1) {
902 JK_ENTER_LOCK(jk_shmem.fd_lock, rc);
903 }
904 #endif
905 return rc;
906 }
907
jk_shm_unlock()908 int jk_shm_unlock()
909 {
910 int rc = JK_TRUE;
911
912 if (!jk_shm_inited_cs)
913 return JK_FALSE;
914 #if defined (WIN32)
915 if (jk_shm_hlock != NULL) {
916 ReleaseMutex(jk_shm_hlock);
917 }
918 #else
919 if (jk_shmem.fd_lock != -1) {
920 JK_LEAVE_LOCK(jk_shmem.fd_lock, rc);
921 }
922 #endif
923 JK_LEAVE_CS(&jk_shmem.cs);
924 return rc;
925 }
926
jk_shm_alloc_ajp_worker(jk_pool_t * p,const char * name,jk_logger_t * l)927 jk_shm_ajp_worker_t *jk_shm_alloc_ajp_worker(jk_pool_t *p, const char *name,
928 jk_logger_t *l)
929 {
930 return (jk_shm_ajp_worker_t *)jk_shm_alloc_worker(p,
931 JK_AJP13_WORKER_TYPE, 0, name, l);
932 }
933
jk_shm_alloc_lb_sub_worker(jk_pool_t * p,int lb_id,const char * name,jk_logger_t * l)934 jk_shm_lb_sub_worker_t *jk_shm_alloc_lb_sub_worker(jk_pool_t *p, int lb_id, const char *name,
935 jk_logger_t *l)
936 {
937 return (jk_shm_lb_sub_worker_t *)jk_shm_alloc_worker(p,
938 JK_LB_SUB_WORKER_TYPE, lb_id, name, l);
939 }
940
jk_shm_alloc_lb_worker(jk_pool_t * p,const char * name,jk_logger_t * l)941 jk_shm_lb_worker_t *jk_shm_alloc_lb_worker(jk_pool_t *p, const char *name,
942 jk_logger_t *l)
943 {
944 return (jk_shm_lb_worker_t *)jk_shm_alloc_worker(p,
945 JK_LB_WORKER_TYPE, 0, name, l);
946 }
947