int jk_shm_open()

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;
}