You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2009/08/14 13:56:17 UTC

svn commit: r804172 - in /commons/sandbox/runtime/trunk/src/main/native: Makefile.in include/arch/hpux/acr_arch_private.h os/hpux/shm.c

Author: mturk
Date: Fri Aug 14 11:56:16 2009
New Revision: 804172

URL: http://svn.apache.org/viewvc?rev=804172&view=rev
Log:
HP-UX doesn't have MAP_ANON

Added:
    commons/sandbox/runtime/trunk/src/main/native/os/hpux/shm.c   (with props)
Modified:
    commons/sandbox/runtime/trunk/src/main/native/Makefile.in
    commons/sandbox/runtime/trunk/src/main/native/include/arch/hpux/acr_arch_private.h

Modified: commons/sandbox/runtime/trunk/src/main/native/Makefile.in
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/Makefile.in?rev=804172&r1=804171&r2=804172&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/Makefile.in (original)
+++ commons/sandbox/runtime/trunk/src/main/native/Makefile.in Fri Aug 14 11:56:16 2009
@@ -174,7 +174,6 @@
 	$(SRCDIR)/os/unix/group.$(OBJ) \
 	$(SRCDIR)/os/unix/user.$(OBJ) \
 	$(SRCDIR)/os/unix/pmutex.$(OBJ) \
-	$(SRCDIR)/os/unix/shm.$(OBJ) \
 	$(SRCDIR)/os/unix/signals.$(OBJ) \
 	$(SRCDIR)/os/unix/syslog.$(OBJ) \
 	$(SRCDIR)/os/unix/time.$(OBJ) \
@@ -184,6 +183,7 @@
 	$(SRCDIR)/os/hpux/platform.$(OBJ) \
 	$(SRCDIR)/os/hpux/pgroup.$(OBJ) \
 	$(SRCDIR)/os/hpux/puser.$(OBJ) \
+	$(SRCDIR)/os/hpux/shm.$(OBJ) \
 	$(SRCDIR)/os/hpux/os.$(OBJ)
 
 ZLIB_OBJS=\

Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/hpux/acr_arch_private.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/hpux/acr_arch_private.h?rev=804172&r1=804171&r2=804172&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/arch/hpux/acr_arch_private.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/arch/hpux/acr_arch_private.h Fri Aug 14 11:56:16 2009
@@ -41,8 +41,8 @@
 /**
  * Temporary APR flags
  */
-#define APR_USE_SHMEM_SHMGET                0
-#define APR_USE_SHMEM_MMAP_ANON             1
+#define APR_USE_SHMEM_SHMGET                1
+#define APR_USE_SHMEM_SHMGET_ANON           1
 #define APR_USE_SYSVSEM_SERIALIZE           1
 #define APR_USE_PTHREAD_SERIALIZE           1 
 #define APR_PROCESS_LOCK_IS_GLOBAL          0
@@ -56,9 +56,9 @@
 #define APR_HAS_XTHREAD_FILES               0
 #define APR_HAS_OS_UUID                     0
 #define APR_TCP_NOPUSH_FLAG                 0
-#define APR_TCP_NODELAY_INHERITED           0
+#define APR_TCP_NODELAY_INHERITED           1
 #define APR_O_NONBLOCK_INHERITED            0
-#define APR_HAS_LARGE_FILES                 0
+#define APR_HAS_LARGE_FILES                 1
 
 /**
  * Temporary APR private flags

Added: commons/sandbox/runtime/trunk/src/main/native/os/hpux/shm.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/hpux/shm.c?rev=804172&view=auto
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/hpux/shm.c (added)
+++ commons/sandbox/runtime/trunk/src/main/native/os/hpux/shm.c Fri Aug 14 11:56:16 2009
@@ -0,0 +1,492 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "acr.h"
+#include "acr_private.h"
+#include "acr_arch.h"
+#include "acr_error.h"
+#include "acr_memory.h"
+#include "acr_string.h"
+#include "acr_descriptor.h"
+#include "acr_shm.h"
+
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/file.h>
+
+#if !defined(SHM_R)
+#define SHM_R 0400
+#endif
+#if !defined(SHM_W)
+#define SHM_W 0200
+#endif
+
+#define ACR_SHM_OWNER   0
+#define ACR_SHM_CHILD   1
+
+typedef struct memblock_t {
+    acr_uint32_t    magic;       /* Is this our memeory */
+    pid_t           creator;     /* Creator's process ID */
+    acr_size_t      size;
+    acr_size_t      length;
+} memblock_t;
+
+struct acr_shm_t {
+    void       *base;           /* base real address */
+    void       *usable;         /* base usable address */
+    acr_size_t  reqsize;        /* requested segment size */
+    acr_size_t  realsize;       /* actual segment size */
+    const char *filename;       /* NULL if anonymous */
+    int         shmid;          /* shmem ID returned from shmget() */
+    key_t       shmkey;
+};
+
+static int shm_owner_cleanup(void *shm, int type, unsigned int flags)
+{
+    int rc = 0;
+    acr_shm_t *m = (acr_shm_t *)shm;
+
+    if (type != ACR_DT_SHM) {
+        return ACR_EINVAL;
+    }
+    /* anonymous shared memory */
+    if (m->filename == NULL) {
+        if (shmdt(m->base) == -1) {
+            rc = ACR_GET_OS_ERROR();
+        }
+    }
+    /* name-based shared memory */
+    else {
+        /* Indicate that the segment is to be destroyed as soon
+         * as all processes have detached. This also disallows any
+         * new attachments to the segment.
+         */
+        if (shmctl(m->shmid, IPC_RMID, NULL) == -1 && errno != EINVAL) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+        if (shmdt(m->base) == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+        if (access(m->filename, F_OK)) {
+            rc = ACR_SUCCESS;
+        }
+        else {
+            if (unlink(m->filename))
+                rc = ACR_GET_OS_ERROR();
+        }
+    }
+cleanup:
+    if (m->filename)
+        free((void *)(m->filename));
+    free(m);
+    return rc;
+}
+
+static int shm_child_cleanup(void *shm, int type, unsigned int flags)
+{
+    int rc = 0;
+    acr_shm_t *m = (acr_shm_t *)shm;
+
+    if (type != ACR_DT_SHM) {
+        return ACR_EINVAL;
+    }
+
+    if (m->filename == NULL) {
+        /* It doesn't make sense to detach from an
+         * anonymous memory segment.
+         */
+        rc = ACR_EINVAL;
+    }
+    else {
+        if (shmdt(m->base) == -1) {
+            rc = ACR_GET_OS_ERROR();
+        }
+    }
+    if (m->filename)
+        free((void *)(m->filename));
+    free(m);
+    return rc;
+}
+
+ACR_DECLARE(int) ACR_ShmClose(JNIEnv *_E, int shm)
+{
+    int rv;
+
+    rv = acr_ioh_close(shm);
+    if (rv  && !IS_INVALID_HANDLE(_E)) {
+        if (rv == EACCES)
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+        else
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rv);
+    }
+    return rv;
+}
+
+ACR_DECLARE(int) ACR_ShmRemove(JNIEnv *_E, const acr_pchar_t *filename)
+{
+    int     rc = 0;
+    int     file;
+    key_t   shmkey;
+    int     shmid;
+
+    /* Presume that the file already exists; just open for writing.
+     * Mode is not needed cause we don't use O_CREAT flag.
+     */
+    file = open(filename, O_WRONLY);
+    if (file < 0) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+
+    /* ftok() (on solaris at least) requires that the file actually
+     * exist before calling ftok().
+     */
+    shmkey = ftok(filename, 1);
+    if (shmkey == (key_t)-1) {
+        rc = ACR_GET_OS_ERROR();
+        close(file);
+        goto cleanup;
+    }
+    close(file);
+
+    if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+
+    /* Indicate that the segment is to be destroyed as soon
+     * as all processes have detached. This also disallows any
+     * new attachments to the segment.
+     */
+    if (shmctl(shmid, IPC_RMID, NULL) == -1) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+
+cleanup:
+    unlink(filename);
+    if (rc  && !IS_INVALID_HANDLE(_E)) {
+        if (rc == EACCES)
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+        else
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rc);
+    }
+    return rc;
+}
+
+ACR_DECLARE(int) ACR_ShmCreate(JNIEnv *_E, acr_size_t reqsize,
+                               const acr_pchar_t *filename)
+{
+    memblock_t hdr;
+    acr_shm_t *shm = NULL;
+    struct shmid_ds shmbuf;
+    int         file;   /* file where metadata is stored */
+    int         rc = 0;
+    acr_size_t  nbytes;
+
+    if (reqsize > ACR_SIZE_T_MAX) {
+        /* Guard against insane sizes */
+        if (!IS_INVALID_HANDLE(_E)) {
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EINVAL, 0);
+        }
+        ACR_SET_OS_ERROR(ACR_EINVAL);
+        return -1;
+    }
+    shm = ACR_Calloc(_E, THROW_FMARK, sizeof(acr_shm_t));
+    if (!shm)
+        return -1;
+    /* Check if they want anonymous or name-based shared memory */
+    if (filename == NULL) {
+        shm->filename = NULL;    
+        shm->reqsize  = reqsize;
+        shm->realsize = reqsize;
+        shm->shmkey   = IPC_PRIVATE
+        shm->shmid    = shmget(shm->shmkey, shm->realsize,
+                               SHM_R | SHM_W | IPC_CREAT);
+        if (shm->shmid < 0) {
+            rc =  ACR_GET_OS_ERROR();
+            goto anonerr;
+        }
+        shm->base     = shmat(shm->shmid, NULL, 0);
+        if (shm->base == (void *)-1) {
+            rc =  ACR_GET_OS_ERROR();
+            goto anonerr;
+        }
+        shmbuf.shm_perm.uid = uid;
+        shmbuf.shm_perm.gid = gid;
+        if (shmctl(shm->shmid, IPC_SET, &shmbuf) == -1) {
+            rc =  ACR_GET_OS_ERROR();
+            goto anonerr;
+        }
+        /* Remove the segment once use count hits zero.
+         * We will not attach to this segment again, since it is
+         * anonymous memory, so it is ok to mark it for deletion.
+         */
+        if (shmctl(shm->shmid, IPC_RMID, NULL) == -1) {
+            rc =  ACR_GET_OS_ERROR();
+            goto anonerr;
+        }
+        shm->usable = shm->base;
+anonerr:
+        if (rc) {
+            free(shm);
+            if (!IS_INVALID_HANDLE(_E)) {
+                if (rc == EACCES)
+                    ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+                else
+                    ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rc);
+            }
+            ACR_SET_OS_ERROR(rc);
+            return -1;
+        }
+    }
+    /* Name-based shared memory */
+    else {
+        shm->reqsize  = reqsize;
+        shm->filename = ACR_StrdupA(_E, THROW_FMARK, filename);
+        if (!shm->filename) {
+            rc =  ACR_GET_OS_ERROR();
+            free(shm);
+            ACR_SET_OS_ERROR(rc);
+            return -1;
+        }
+
+        shm->realsize = reqsize;
+
+        /* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think.
+         * Unlike APR we use 0660 which is less permissive
+         */
+        file = open(filename, O_WRONLY | O_CREAT | O_EXCL, 0660);
+        if (file < 0) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+
+        /* ftok() (on solaris at least) requires that the file actually
+         * exist before calling ftok(). */
+        shm->shmkey = ftok(filename, 1);
+        if (shm->shmkey == (key_t)-1) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+
+        if ((shm->shmid = shmget(shm->shmkey, shm->realsize,
+                                 SHM_R | SHM_W | IPC_CREAT | IPC_EXCL)) < 0) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+
+        if ((shm->base = shmat(shm->shmid, NULL, 0)) == (void *)-1) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+        shm->usable = shm->base;
+
+        if (shmctl(shm->shmid, IPC_STAT, &shmbuf) == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+        shmbuf.shm_perm.uid = getuid();
+        shmbuf.shm_perm.gid = getgid();
+        if (shmctl(shm->shmid, IPC_SET, &shmbuf) == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;
+        }
+
+        nbytes = sizeof(memblock_t);
+        hdr.creator = getpid();
+        hdr.magic   = ACR_SHM_MAGIC;
+        hdr.size    = shm->reqsize;
+        hdr.length  = shm->realsize;
+        do {
+            rc = write(file,(const void *)&hdr, nbytes);
+        } while (rc == (acr_size_t)-1 && errno == EINTR);
+        if (rc == -1) {
+            rc = ACR_GET_OS_ERROR();
+            goto cleanup;            
+        }
+cleanup:
+        if (file > 0)
+            rc = close(file);
+        if (rc) {
+            free((void *)(shm->filename));
+            free(shm);
+            if (!IS_INVALID_HANDLE(_E)) {
+                if (rc == EACCES)
+                    ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+                else
+                    ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rc);
+            }
+            ACR_SET_OS_ERROR(rc);
+            shm = NULL;
+        }
+    }
+    if (shm) {
+        rc = acr_ioh_open(shm, ACR_DT_SHM, ACR_SHM_OWNER, shm_owner_cleanup);
+        return rc;
+    }
+    else
+        return -1;
+}
+
+ACR_DECLARE(int) ACR_ShmAttach(JNIEnv *_E,
+                               const acr_pchar_t *filename)
+{
+    memblock_t hdr;
+    acr_shm_t *shm = NULL;
+    int         file;   /* file where metadata is stored */
+    int         rc;
+    acr_size_t  nbytes;
+
+    if (!filename) {
+        ACR_SET_OS_ERROR(ACR_EINVAL);
+        return -1;
+    }
+    shm = ACR_Calloc(_E, THROW_FMARK, sizeof(acr_shm_t));
+    if (!shm)
+        return -1;
+    shm->filename = ACR_StrdupA(_E, THROW_FMARK, filename);
+    if (!shm->filename) {
+        rc =  ACR_GET_OS_ERROR();
+        free(shm);
+        ACR_SET_OS_ERROR(rc);
+        return -1;
+    }
+
+    file = open(filename, O_RDONLY);
+    if (file < 0) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+
+    nbytes = sizeof(memblock_t);
+
+    do {
+        rc = read(file, (void *)&hdr, nbytes);
+    } while (rc == -1 && errno == EINTR);
+    if (rc != nbytes) {
+        /* Wrong format */
+        rc = EBADF;
+        close(file);
+        goto cleanup;
+    }
+    rc = close(file);
+    if (rc) {
+        goto cleanup;
+    }
+    if (hdr.magic != ACR_SHM_MAGIC) {
+        /* Not created by us or corrupted */
+        rc = ACR_EBADF;
+        goto cleanup;
+    }
+    shm->reqsize = hdr.size;
+    shm->shmkey  = ftok(filename, 1);
+    if (shm->shmkey == (key_t)-1) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+    if ((shm->shmid = shmget(shm->shmkey, 0, SHM_R | SHM_W)) == -1) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+    if ((shm->base = shmat(shm->shmid, NULL, 0)) == (void *)-1) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+    shm->usable   = shm->base;
+    shm->realsize = shm->reqsize;
+
+cleanup:
+    if (rc) {
+        free((void *)(shm->filename));
+        free(shm);
+        if (!IS_INVALID_HANDLE(_E)) {
+            if (rc == EACCES)
+                ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+            else
+                ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rc);
+        }
+        ACR_SET_OS_ERROR(rc);
+        shm = NULL;
+    }
+    if (shm) {
+        rc = acr_ioh_open(shm, ACR_DT_SHM, ACR_SHM_CHILD, shm_child_cleanup);
+        return rc;
+    }
+    else
+        return -1;
+}
+
+ACR_DECLARE(int) ACR_ShmPermSet(JNIEnv *_E, int shm, int perms,
+                                acr_uid_t uid, acr_uid_t gid)
+{
+    int rc = 0;
+    struct shmid_ds shmbuf;
+    int shmid;
+    acr_shm_t *m = (acr_shm_t *)ACR_IOH(shm);
+
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(shm) != ACR_DT_SHM) {
+        rc = ACR_EINVAL;
+        goto cleanup;
+    }        
+    if ((shmid = shmget(m->shmkey, 0, SHM_R | SHM_W)) == -1) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+    shmbuf.shm_perm.uid  = uid;
+    shmbuf.shm_perm.gid  = gid;
+    shmbuf.shm_perm.mode = ACR_UnixPermsToMode(perms);
+    if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
+        rc = ACR_GET_OS_ERROR();
+        goto cleanup;
+    }
+
+cleanup:
+    if (rc && !IS_INVALID_HANDLE(_E)) {
+        if (rc == EACCES)
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_ESECURITY, 0);
+        else
+            ACR_ThrowException(_E, THROW_NMARK, ACR_EX_EIO, rc);
+    }
+    return rc;
+}
+
+ACR_DECLARE(void *) ACR_ShmGetBaseAddr(int shm)
+{
+    acr_shm_t *m = (acr_shm_t *)ACR_IOH(shm);
+
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(shm) != ACR_DT_SHM) {
+        ACR_SET_OS_ERROR(ACR_EINVAL);
+        return NULL;
+    }
+    else
+        return m->usable;
+}
+
+ACR_DECLARE(acr_size_t) ACR_ShmGetSize(int shm)
+{
+    acr_shm_t *m = (acr_shm_t *)ACR_IOH(shm);
+    if (IS_INVALID_HANDLE(m) || ACR_IOH_TYPE(shm) != ACR_DT_SHM) {
+        ACR_SET_OS_ERROR(ACR_EINVAL);
+        return 0;
+    }
+    else
+        return m->reqsize;
+}
+

Propchange: commons/sandbox/runtime/trunk/src/main/native/os/hpux/shm.c
------------------------------------------------------------------------------
    svn:eol-style = native