]> granicus.if.org Git - apache/commitdiff
Make the prefork MPM use APR shared memory for it's scoreboard.
authorRyan Bloom <rbb@apache.org>
Thu, 10 Feb 2000 23:46:33 +0000 (23:46 +0000)
committerRyan Bloom <rbb@apache.org>
Thu, 10 Feb 2000 23:46:33 +0000 (23:46 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84609 13f79535-47bb-0310-9956-ffa450edef68

server/mpm/prefork/prefork.c

index 05a0fe27e7afa9c19fefdedf7e6912a2c87b4911..cfa45341e0a2373739788844b001cca5d50ab081 100644 (file)
 #include <sys/times.h>
 #include <sys/types.h>
 #include <sys/wait.h>
-#ifdef USE_SHMGET_SCOREBOARD
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif
 
 
 
@@ -906,444 +902,45 @@ static int reap_other_child(int pid, ap_wait_t status)
 }
 #endif
 
-/*****************************************************************
- *
- * Dealing with the scoreboard... a lot of these variables are global
- * only to avoid getting clobbered by the longjmp() that happens when
- * a hard timeout expires...
- *
- * We begin with routines which deal with the file itself... 
- */
-
-#if defined(USE_OS2_SCOREBOARD)
-
-/* The next two routines are used to access shared memory under OS/2.  */
-/* This requires EMX v09c to be installed.                           */
-
-caddr_t create_shared_heap(const char *name, size_t size)
-{
-    ULONG rc;
-    void *mem;
-    Heap_t h;
-
-    rc = DosAllocSharedMem(&mem, name, size,
-                          PAG_COMMIT | PAG_READ | PAG_WRITE);
-    if (rc != 0)
-       return NULL;
-    h = _ucreate(mem, size, !_BLOCK_CLEAN, _HEAP_REGULAR | _HEAP_SHARED,
-                NULL, NULL);
-    if (h == NULL)
-       DosFreeMem(mem);
-    return (caddr_t) h;
-}
-
-caddr_t get_shared_heap(const char *Name)
-{
-
-    PVOID BaseAddress;         /* Pointer to the base address of
-                                  the shared memory object */
-    ULONG AttributeFlags;      /* Flags describing characteristics
-                                  of the shared memory object */
-    APIRET rc;                 /* Return code */
-
-    /* Request read and write access to */
-    /*   the shared memory object       */
-    AttributeFlags = PAG_WRITE | PAG_READ;
-
-    rc = DosGetNamedSharedMem(&BaseAddress, Name, AttributeFlags);
-
-    if (rc != 0) {
-       printf("DosGetNamedSharedMem error: return code = %ld", rc);
-       return 0;
-    }
-
-    return BaseAddress;
-}
-
-static void setup_shared_mem(ap_context_t *p)
-{
-    caddr_t m;
-
-    int rc;
-
-    m = (caddr_t) create_shared_heap("\\SHAREMEM\\SCOREBOARD", SCOREBOARD_SIZE);
-    if (m == 0) {
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "%s: Could not create OS/2 Shared memory pool.",
-                    ap_server_argv0);
-       exit(APEXIT_INIT);
-    }
-
-    rc = _uopen((Heap_t) m);
-    if (rc != 0) {
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL,
-               "%s: Could not uopen() newly created OS/2 Shared memory pool.",
-               ap_server_argv0);
-    }
-    ap_scoreboard_image = (scoreboard *) m;
-    ap_scoreboard_image->global.running_generation = 0;
-}
-
-static void reopen_scoreboard(ap_context_t *p)
-{
-    caddr_t m;
-    int rc;
-
-    m = (caddr_t) get_shared_heap("\\SHAREMEM\\SCOREBOARD");
-    if (m == 0) {
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "%s: Could not find existing OS/2 Shared memory pool.",
-                    ap_server_argv0);
-       exit(APEXIT_INIT);
-    }
+#if APR_HAS_SHARED_MEMORY
+#include "apr_shmem.h"
 
-    rc = _uopen((Heap_t) m);
-    ap_scoreboard_image = (scoreboard *) m;
-}
-
-#elif defined(USE_POSIX_SCOREBOARD)
-#include <sys/mman.h>
-/* 
- * POSIX 1003.4 style
- *
- * Note 1: 
- * As of version 4.23A, shared memory in QNX must reside under /dev/shmem,
- * where no subdirectories allowed.
- *
- * POSIX shm_open() and shm_unlink() will take care about this issue,
- * but to avoid confusion, I suggest to redefine scoreboard file name
- * in httpd.conf to cut "logs/" from it. With default setup actual name
- * will be "/dev/shmem/logs.apache_status". 
- * 
- * If something went wrong and Apache did not unlinked this object upon
- * exit, you can remove it manually, using "rm -f" command.
- * 
- * Note 2:
- * <sys/mman.h> in QNX defines MAP_ANON, but current implementation 
- * does NOT support BSD style anonymous mapping. So, the order of 
- * conditional compilation is important: 
- * this #ifdef section must be ABOVE the next one (BSD style).
- *
- * I tested this stuff and it works fine for me, but if it provides 
- * trouble foR YOU, JUst comment out USE_MMAP_SCOREBOARD in QNX section
- * of ap_config.h
- *
- * June 5, 1997, 
- * Igor N. Kovalenko -- infoh@mail.wplus.net
- */
+static ap_shmem_t *scoreboard_shm = NULL;
 
-static void cleanup_shared_mem(void *d)
+static ap_status_t cleanup_shared_mem(void *d)
 {
-    shm_unlink(ap_scoreboard_fname);
+    mm_free(scoreboard_shm, ap_scoreboard_image);
+    ap_scoreboard_image = NULL;
+    ap_shm_destroy(scoreboard_shm);
 }
 
 static void setup_shared_mem(ap_context_t *p)
 {
     char buf[512];
-    caddr_t m;
-    int fd;
+    const char *fname;
 
-    fd = shm_open(ap_scoreboard_fname, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
-    if (fd == -1) {
+    fname = ap_server_root_relative(p, ap_scoreboard_fname);
+    if (ap_shm_init(&scoreboard_shm, SCOREBOARD_SIZE + 40, fname) != APR_SUCCESS) {
        ap_snprintf(buf, sizeof(buf), "%s: could not open(create) scoreboard",
                    ap_server_argv0);
        perror(buf);
        exit(APEXIT_INIT);
     }
-    if (ltrunc(fd, (off_t) SCOREBOARD_SIZE, SEEK_SET) == -1) {
-       ap_snprintf(buf, sizeof(buf), "%s: could not ltrunc scoreboard",
-                   ap_server_argv0);
-       perror(buf);
-       shm_unlink(ap_scoreboard_fname);
-       exit(APEXIT_INIT);
-    }
-    if ((m = (caddr_t) mmap((caddr_t) 0,
-                           (size_t) SCOREBOARD_SIZE, PROT_READ | PROT_WRITE,
-                           MAP_SHARED, fd, (off_t) 0)) == (caddr_t) - 1) {
-       ap_snprintf(buf, sizeof(buf), "%s: cannot mmap scoreboard",
+    ap_scoreboard_image = ap_shm_malloc(scoreboard_shm, SCOREBOARD_SIZE); 
+    if (ap_scoreboard_image == NULL) {
+       ap_snprintf(buf, sizeof(buf), "%s: cannot allocate scoreboard",
                    ap_server_argv0);
        perror(buf);
-       shm_unlink(ap_scoreboard_fname);
+       ap_shm_destroy(scoreboard_shm);
        exit(APEXIT_INIT);
     }
-    close(fd);
     ap_register_cleanup(p, NULL, cleanup_shared_mem, ap_null_cleanup);
-    ap_scoreboard_image = (scoreboard *) m;
     ap_scoreboard_image->global.running_generation = 0;
 }
 
 static void reopen_scoreboard(ap_context_t *p)
 {
 }
-
-#elif defined(USE_MMAP_SCOREBOARD)
-
-static void setup_shared_mem(ap_context_t *p)
-{
-    caddr_t m;
-
-#if defined(MAP_ANON)
-/* BSD style */
-#ifdef CONVEXOS11
-    /*
-     * 9-Aug-97 - Jeff Venters (venters@convex.hp.com)
-     * ConvexOS maps address space as follows:
-     *   0x00000000 - 0x7fffffff : Kernel
-     *   0x80000000 - 0xffffffff : User
-     * Start mmapped area 1GB above start of text.
-     *
-     * Also, the length requires a pointer as the actual length is
-     * returned (rounded up to a page boundary).
-     */
-    {
-       unsigned len = SCOREBOARD_SIZE;
-
-       m = mmap((caddr_t) 0xC0000000, &len,
-                PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, NOFD, 0);
-    }
-#elif defined(MAP_TMPFILE)
-    {
-       char mfile[] = "/tmp/apache_shmem_XXXX";
-       int fd = mkstemp(mfile);
-       if (fd == -1) {
-           perror("open");
-           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                         "%s: Could not open %s", ap_server_argv0, mfile);
-           exit(APEXIT_INIT);
-       }
-       m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
-               PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-       if (m == (caddr_t) - 1) {
-           perror("mmap");
-           ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                         "%s: Could not mmap %s", ap_server_argv0, mfile);
-           exit(APEXIT_INIT);
-       }
-       close(fd);
-       unlink(mfile);
-    }
-#else
-    m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
-            PROT_READ | PROT_WRITE, MAP_ANON | MAP_SHARED, -1, 0);
-#endif
-    if (m == (caddr_t) - 1) {
-       perror("mmap");
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "%s: Could not mmap memory", ap_server_argv0);
-       exit(APEXIT_INIT);
-    }
-#else
-/* Sun style */
-    int fd;
-
-    fd = open("/dev/zero", O_RDWR);
-    if (fd == -1) {
-       perror("open");
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "%s: Could not open /dev/zero", ap_server_argv0);
-       exit(APEXIT_INIT);
-    }
-    m = mmap((caddr_t) 0, SCOREBOARD_SIZE,
-            PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-    if (m == (caddr_t) - 1) {
-       perror("mmap");
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "%s: Could not mmap /dev/zero", ap_server_argv0);
-       exit(APEXIT_INIT);
-    }
-    close(fd);
-#endif
-    ap_scoreboard_image = (scoreboard *) m;
-    ap_scoreboard_image->global.running_generation = 0;
-}
-
-static void reopen_scoreboard(ap_context_t *p)
-{
-}
-
-#elif defined(USE_SHMGET_SCOREBOARD)
-static key_t shmkey = IPC_PRIVATE;
-static int shmid = -1;
-
-static void setup_shared_mem(ap_context_t *p)
-{
-    struct shmid_ds shmbuf;
-#ifdef MOVEBREAK
-    char *obrk;
-#endif
-
-    if ((shmid = shmget(shmkey, SCOREBOARD_SIZE, IPC_CREAT | SHM_R | SHM_W)) == -1) {
-#ifdef LINUX
-       if (errno == ENOSYS) {
-           ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_EMERG, 0, server_conf,
-                        "Your kernel was built without CONFIG_SYSVIPC\n"
-                        "%s: Please consult the Apache FAQ for details",
-                        ap_server_argv0);
-       }
-#endif
-       ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf,
-                   "could not call shmget");
-       exit(APEXIT_INIT);
-    }
-
-    ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, server_conf,
-               "created shared memory segment #%d", shmid);
-
-#ifdef MOVEBREAK
-    /*
-     * Some SysV systems place the shared segment WAY too close
-     * to the dynamic memory break point (sbrk(0)). This severely
-     * limits the use of malloc/sbrk in the program since sbrk will
-     * refuse to move past that point.
-     *
-     * To get around this, we move the break point "way up there",
-     * attach the segment and then move break back down. Ugly
-     */
-    if ((obrk = sbrk(MOVEBREAK)) == (char *) -1) {
-       ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
-           "sbrk() could not move break");
-    }
-#endif
-
-#define BADSHMAT       ((scoreboard *)(-1))
-    if ((ap_scoreboard_image = (scoreboard *) shmat(shmid, 0, 0)) == BADSHMAT) {
-       ap_log_error(APLOG_MARK, APLOG_EMERG, errno, server_conf, "shmat error");
-       /*
-        * We exit below, after we try to remove the segment
-        */
-    }
-    else {                     /* only worry about permissions if we attached the segment */
-       if (shmctl(shmid, IPC_STAT, &shmbuf) != 0) {
-           ap_log_error(APLOG_MARK, APLOG_ERR, errno, server_conf,
-               "shmctl() could not stat segment #%d", shmid);
-       }
-       else {
-           shmbuf.shm_perm.uid = unixd_config.user_id;
-           shmbuf.shm_perm.gid = unixd_config.group_id;
-           if (shmctl(shmid, IPC_SET, &shmbuf) != 0) {
-               ap_log_error(APLOG_MARK, APLOG_ERR, errno, server_conf,
-                   "shmctl() could not set segment #%d", shmid);
-           }
-       }
-    }
-    /*
-     * We must avoid leaving segments in the kernel's
-     * (small) tables.
-     */
-    if (shmctl(shmid, IPC_RMID, NULL) != 0) {
-       ap_log_error(APLOG_MARK, APLOG_WARNING, errno, server_conf,
-               "shmctl: IPC_RMID: could not remove shared memory segment #%d",
-               shmid);
-    }
-    if (ap_scoreboard_image == BADSHMAT)       /* now bailout */
-       exit(APEXIT_INIT);
-
-#ifdef MOVEBREAK
-    if (obrk == (char *) -1)
-       return;                 /* nothing else to do */
-    if (sbrk(-(MOVEBREAK)) == (char *) -1) {
-       ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
-           "sbrk() could not move break back");
-    }
-#endif
-    ap_scoreboard_image->global.running_generation = 0;
-}
-
-static void reopen_scoreboard(ap_context_t *p)
-{
-}
-
-#elif defined(USE_TPF_SCOREBOARD)
-
-static void cleanup_scoreboard_heap()
-{
-    int rv;
-    rv = rsysc(ap_scoreboard_image, SCOREBOARD_FRAMES, SCOREBOARD_NAME);
-    if(rv == RSYSC_ERROR) {
-        ap_log_error(APLOG_MARK, APLOG_ERR, server_conf,
-            "rsysc() could not release scoreboard system heap");
-    }
-}
-
-static void setup_shared_mem(ap_context_t *p)
-{
-    cinfc(CINFC_WRITE, CINFC_CMMCTK2);
-    ap_scoreboard_image = (scoreboard *) gsysc(SCOREBOARD_FRAMES, SCOREBOARD_NAME);
-
-    if (!ap_scoreboard_image) {
-        ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "httpd: Could not create scoreboard system heap storage.");
-        exit(APEXIT_INIT);
-    }
-
-    ap_register_cleanup(p, NULL, cleanup_scoreboard_heap, ap_null_cleanup);
-    ap_scoreboard_image->global.running_generation = 0;
-}
-
-static void reopen_scoreboard(ap_context_t *p)
-{
-    cinfc(CINFC_WRITE, CINFC_CMMCTK2);
-}
-
-#else
-#define SCOREBOARD_FILE
-static scoreboard _scoreboard_image;
-static int scoreboard_fd = -1;
-
-/* XXX: things are seriously screwed if we ever have to do a partial
- * read or write ... we could get a corrupted scoreboard
- */
-static int force_write(int fd, void *buffer, int bufsz)
-{
-    int rv, orig_sz = bufsz;
-
-    do {
-       rv = write(fd, buffer, bufsz);
-       if (rv > 0) {
-           buffer = (char *) buffer + rv;
-           bufsz -= rv;
-       }
-    } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
-
-    return rv < 0 ? rv : orig_sz - bufsz;
-}
-
-static int force_read(int fd, void *buffer, int bufsz)
-{
-    int rv, orig_sz = bufsz;
-
-    do {
-       rv = read(fd, buffer, bufsz);
-       if (rv > 0) {
-           buffer = (char *) buffer + rv;
-           bufsz -= rv;
-       }
-    } while ((rv > 0 && bufsz > 0) || (rv == -1 && errno == EINTR));
-
-    return rv < 0 ? rv : orig_sz - bufsz;
-}
-
-static void cleanup_scoreboard_file(void *foo)
-{
-    unlink(ap_scoreboard_fname);
-}
-
-void reopen_scoreboard(ap_context_t *p)
-{
-    if (scoreboard_fd != -1)
-       ap_pclosef(p, scoreboard_fd);
-
-#ifdef TPF
-    ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
-#endif /* TPF */
-    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0666);
-    if (scoreboard_fd == -1) {
-       perror(ap_scoreboard_fname);
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "Cannot open scoreboard file:");
-       clean_child_exit(1);
-    }
-}
 #endif
 
 /* Called by parent process */
@@ -1351,33 +948,16 @@ static void reinit_scoreboard(ap_context_t *p)
 {
     int running_gen = 0;
     if (ap_scoreboard_image)
-       running_gen = ap_scoreboard_image->global.running_generation;
+        running_gen = ap_scoreboard_image->global.running_generation;
 
-#ifndef SCOREBOARD_FILE
     if (ap_scoreboard_image == NULL) {
-       setup_shared_mem(p);
+        setup_shared_mem(p);
     }
     memset(ap_scoreboard_image, 0, SCOREBOARD_SIZE);
     ap_scoreboard_image->global.running_generation = running_gen;
-#else
-    ap_scoreboard_image = &_scoreboard_image;
-    ap_scoreboard_fname = ap_server_root_relative(p, ap_scoreboard_fname);
-
-    scoreboard_fd = ap_popenf(p, ap_scoreboard_fname, O_CREAT | O_BINARY | O_RDWR, 0644);
-    if (scoreboard_fd == -1) {
-       perror(ap_scoreboard_fname);
-       ap_log_error(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, NULL, 
-                     "Cannot open scoreboard file:");
-       exit(APEXIT_INIT);
-    }
-    ap_register_cleanup(p, NULL, cleanup_scoreboard_file, ap_null_cleanup);
-
-    memset((char *) ap_scoreboard_image, 0, sizeof(*ap_scoreboard_image));
-    ap_scoreboard_image->global.running_generation = running_gen;
-    force_write(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
-#endif
 }
 
+
 /* Routines called to deal with the scoreboard image
  * --- note that we do *not* need write locks, since update_child_status
  * only updates a *single* record in place, and only one process writes to
@@ -1388,12 +968,12 @@ static void reinit_scoreboard(ap_context_t *p)
  * since when the parent is writing an entry, it's only noting SERVER_DEAD
  * anyway.
  */
-
 ap_inline void ap_sync_scoreboard_image(void)
 {
 #ifdef SCOREBOARD_FILE
     lseek(scoreboard_fd, 0L, 0);
-    force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image));
+    force_read(scoreboard_fd, ap_scoreboard_image, sizeof(*ap_scoreboard_image))
+;
 #endif
 }
 
@@ -1403,7 +983,7 @@ API_EXPORT(int) ap_exists_scoreboard_image(void)
 }
 
 static ap_inline void put_scoreboard_info(int child_num,
-                                      short_score *new_score_rec)
+                                       short_score *new_score_rec)
 {
 #ifdef SCOREBOARD_FILE
     lseek(scoreboard_fd, (long) child_num * sizeof(short_score), 0);
@@ -1421,7 +1001,6 @@ int ap_update_child_status(int child_num, int status, request_rec *r)
 
     ap_check_signals();
 
-    ap_sync_scoreboard_image();
     ss = &ap_scoreboard_image->servers[child_num];
     old_status = ss->status;
     ss->status = status;
@@ -1800,7 +1379,9 @@ static void restart(int sig)
        return;
     }
     restart_pending = 1;
-    is_graceful = sig == SIGUSR1;
+    if (is_graceful = sig == SIGUSR1) {
+        ap_kill_cleanup(pconf, NULL, cleanup_shared_mem);
+    }
 }
 
 static void set_signals(void)
@@ -2223,7 +1804,6 @@ static void child_main(int child_num_arg)
         * third party code.
         */
        signal(SIGUSR1, SIG_IGN);
-
        /*
         * We now have a connection, so set it up with the appropriate
         * socket options, file descriptors, and read/write buffers.
@@ -2736,7 +2316,6 @@ int ap_mpm_run(ap_context_t *_pconf, ap_context_t *plog, server_rec *s)
     /* we've been told to restart */
     signal(SIGHUP, SIG_IGN);
     signal(SIGUSR1, SIG_IGN);
-
     if (one_process) {
        /* not worth thinking about */
        return 1;