in native/common/jk_shm.c [193:364]
int jk_shm_open(const char *fname, int sz, jk_log_context_t *l)
{
int rc = -1;
int attached = 0;
char lkname[MAX_PATH];
char shname[MAX_PATH] = "";
JK_TRACE_ENTER(l);
if (!jk_shm_inited_cs) {
jk_shm_inited_cs = 1;
JK_INIT_CS(&jk_shmem.cs, rc);
}
JK_ENTER_CS(&jk_shmem.cs);
if (jk_shmem.hdr) {
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG, "Shared memory is already opened");
JK_TRACE_EXIT(l);
JK_LEAVE_CS(&jk_shmem.cs);
return 0;
}
if (sz < 0) {
jk_log(l, JK_LOG_ERROR, "Invalid shared memory size (%d)", sz);
JK_TRACE_EXIT(l);
return EINVAL;
}
jk_shmem.size = JK_SHM_ALIGN(JK_SHM_SLOT_SIZE + sz);
jk_shm_map = NULL;
jk_shm_hlock = NULL;
if (fname) {
int i;
SIZE_T shmsz = 0;
strcpy(shname, "Local\\");
strncat(shname, fname, MAX_PATH - 8);
for(i = 7; i < (int)strlen(shname); i++) {
if (!jk_isalnum(shname[i]))
shname[i] = '_';
else
shname[i] = toupper(shname[i]);
}
strcpy(lkname, shname);
strncat(lkname, "_MUTEX", MAX_PATH - 1);
jk_shm_hlock = CreateMutex(jk_get_sa_with_null_dacl(), TRUE, lkname);
if (jk_shm_hlock == NULL) {
if (GetLastError() == ERROR_ALREADY_EXISTS) {
attached = 1;
jk_shm_hlock = OpenMutex(MUTEX_ALL_ACCESS, FALSE, lkname);
}
}
else if (GetLastError() == ERROR_ALREADY_EXISTS)
attached = 1;
if (jk_shm_hlock == NULL) {
rc = GetLastError();
jk_log(l, JK_LOG_ERROR, "Failed to open shared memory mutex %s with errno=%d",
lkname, rc);
JK_LEAVE_CS(&jk_shmem.cs);
JK_TRACE_EXIT(l);
return rc;
}
if (attached) {
DWORD ws = WaitForSingleObject(jk_shm_hlock, INFINITE);
if (ws == WAIT_FAILED) {
rc = GetLastError();
CloseHandle(jk_shm_hlock);
jk_shm_hlock = NULL;
JK_LEAVE_CS(&jk_shmem.cs);
JK_TRACE_EXIT(l);
return rc;
}
jk_shm_map = OpenFileMapping(FILE_MAP_READ | FILE_MAP_WRITE, FALSE, shname);
if (jk_shm_map == NULL) {
rc = GetLastError();
jk_log(l, JK_LOG_ERROR, "Failed to open shared memory %s with errno=%d",
shname, rc);
}
}
if (jk_shm_map == NULL) {
shmsz = jk_shmem.size;
jk_shm_map = CreateFileMapping(INVALID_HANDLE_VALUE,
jk_get_sa_with_null_dacl(),
PAGE_READWRITE,
0,
(DWORD)shmsz,
shname);
}
if (jk_shm_map == NULL || jk_shm_map == INVALID_HANDLE_VALUE) {
rc = GetLastError();
jk_log(l, JK_LOG_ERROR, "Failed to map shared memory %s with errno=%d",
fname, rc);
CloseHandle(jk_shm_hlock);
jk_shm_hlock = NULL;
jk_shm_map = NULL;
JK_LEAVE_CS(&jk_shmem.cs);
JK_TRACE_EXIT(l);
return rc;
}
jk_shmem.hdr = (jk_shm_header_t *)MapViewOfFile(jk_shm_map,
FILE_MAP_READ | FILE_MAP_WRITE,
0,
0,
shmsz);
}
else
jk_shmem.hdr = (jk_shm_header_t *)calloc(1, jk_shmem.size);
if (!jk_shmem.hdr) {
rc = GetLastError();
if (jk_shm_map) {
CloseHandle(jk_shm_map);
jk_shm_map = NULL;
}
if (jk_shm_hlock) {
CloseHandle(jk_shm_hlock);
jk_shm_hlock = NULL;
}
JK_LEAVE_CS(&jk_shmem.cs);
JK_TRACE_EXIT(l);
return rc;
}
if (!jk_shmem.filename) {
if (shname[0])
jk_shmem.filename = strdup(shname);
else
jk_shmem.filename = strdup("memory");
}
jk_shmem.fd = 0;
jk_shmem.attached = attached;
if (!attached) {
memset(jk_shmem.hdr, 0, jk_shmem.size);
memcpy(jk_shmem.hdr->h.data.magic, shm_signature,
JK_SHM_MAGIC_SIZ);
jk_shmem.hdr->h.data.size = sz;
jk_shmem.hdr->h.data.childs = 1;
jk_shmem.hdr->h.data.maintain_checking = 0;
jk_shmem.hdr->h.data.maintain_time = time(NULL);
}
else {
jk_shmem.hdr->h.data.childs++;
/*
* Reset the shared memory so that
* alloc works even for attached memory.
* XXX: This might break already used memory
* if the number of workers change between
* open and attach or between two attach operations.
*/
#if 0
if (jk_shmem.hdr->h.data.childs > 1) {
if (JK_IS_DEBUG_LEVEL(l)) {
jk_log(l, JK_LOG_DEBUG,
"Resetting the shared memory for child %d",
jk_shmem.hdr->h.data.childs);
}
}
jk_shmem.hdr->h.data.pos = 0;
jk_shmem.hdr->h.data.workers = 0;
#endif
}
if (jk_shm_hlock != NULL) {
/* Unlock shared memory */
ReleaseMutex(jk_shm_hlock);
}
JK_LEAVE_CS(&jk_shmem.cs);
if (JK_IS_DEBUG_LEVEL(l))
jk_log(l, JK_LOG_DEBUG,
"%s shared memory %s [%d] size=%u workers=%d free=%u addr=%#lx",
attached ? "Attached" : "Initialized",
jk_shm_name(),
jk_shmem.hdr->h.data.childs,
jk_shmem.size, jk_shmem.hdr->h.data.workers - 1,
jk_shmem.hdr->h.data.size - jk_shmem.hdr->h.data.pos,
jk_shmem.hdr);
JK_TRACE_EXIT(l);
return 0;
}