Here is initial patch:

- only for unix, if this OK I will write for other platforms
- Tested on linux RH 8.0 and solaris 9
- New test case added in testshm.c

Please review it so I can provide patch for other platforms ASAP.

Thanks
Amit

Joe Orton wrote:
On Fri, May 28, 2004 at 12:31:37PM +0530, Amit Athavale wrote:
  
It would be very useful for programmers. They could simply do one of the
following to avoid headaches of admins :)

- call apr_shm_remove right before apr_shm_create()
- detect unclean shutdown case and call apr_shm_remove()

I could prepare a patch for this if people are happy with this idea ;)
    

Great, yes please!

joe

  

Index: apr_shm.h
===================================================================
RCS file: /home/cvspublic/apr/include/apr_shm.h,v
retrieving revision 1.5.2.1
diff -r1.5.2.1 apr_shm.h
71a72,86
> 
> /**
>  * Remove shared memory segment associated with a file.
>  * @param filename The file associated with shared-memory segment which
>  *        needs to be removed
>  * @param pool To be used for file operations
>  * @remark This function is only supported for name-based shared 
>  *         memory segments. This function will return APR_ENOTIMPL if 
>  *         anonymous shared memory is prefered over name-based shared memory.
>  *         
>  */
> APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
>                                          apr_pool_t *pool);
> 
> 
Index: shm.c
===================================================================
RCS file: /home/cvspublic/apr/shmem/unix/shm.c,v
retrieving revision 1.21.2.2
diff -u -r1.21.2.2 shm.c
--- shm.c       26 Feb 2004 21:18:01 -0000      1.21.2.2
+++ shm.c       28 May 2004 11:21:23 -0000
@@ -377,6 +377,70 @@
     return APR_ENOTIMPL;
 }
 
+APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename,
+                                         apr_pool_t *pool)
+{
+    apr_status_t rv;
+#if APR_USE_SHMEM_SHMGET
+    apr_status_t status;
+    apr_file_t *file;  
+    key_t shmkey;
+    int shmid;
+#endif
+
+#if APR_USE_SHMEM_MMAP_TMP
+    rv = apr_file_remove(filename, pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    return APR_SUCCESS;
+#endif
+#if APR_USE_SHMEM_MMAP_SHM
+    if (shm_unlink(filename) == -1) {
+        return errno;
+    }
+    return APR_SUCCESS;
+#endif
+#if APR_USE_SHMEM_SHMGET
+    /* At this point we don't know whether file exists or not
+     * so opening it with only CREATE flag i.e. without EXCL
+    */
+    status = apr_file_open(&file, filename,
+                           APR_WRITE | APR_CREATE,
+                           APR_OS_DEFAULT, pool);
+    if (status != APR_SUCCESS) {
+        return status;
+    }
+
+    /* ftok() (on solaris at least) requires that the file actually
+     * exist before calling ftok(). */
+    shmkey = ftok(filename, 1);
+    if (shmkey == (key_t)-1) {
+        return errno;
+    }
+
+    if ((shmid = shmget(shmkey, 0, SHM_R | SHM_W)) < 0) {
+        return errno;
+    }
+
+    /* 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) {
+        return errno;
+    }
+    rv = apr_file_remove(filename, pool);
+    if (rv != APR_SUCCESS) {
+        return rv;
+    }
+    return APR_SUCCESS;
+#endif
+
+    /* No support for anonymous shm */
+    return APR_ENOTIMPL;
+} 
+                                         
+
 APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m)
 {
     return apr_pool_cleanup_run(m->pool, m, shm_cleanup_owner);
Index: testshm.c
===================================================================
RCS file: /home/cvspublic/apr/test/testshm.c,v
retrieving revision 1.8.2.1
diff -r1.8.2.1 testshm.c
247a248,297
> static apr_status_t test_named_remove(apr_pool_t *parpool)
> {
>     apr_status_t rv;
>     apr_pool_t *pool;
>     apr_shm_t *shm;
>     int exit_int;
> 
>     rv = apr_pool_create(&pool, parpool);
>     if (rv != APR_SUCCESS) {
>         fprintf(stderr, "Error creating child pool\n");
>         return rv;
>     }
> 
>     printf("Creating named shared memory block first time(%"
>            APR_SIZE_T_FMT " bytes)........", SHARED_SIZE);
>     rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, pool);
>     if (rv != APR_SUCCESS) {
>         fprintf(stderr, "Error allocating shared memory block\n");
>         return rv;
>     }
>     fprintf(stdout, "OK\n");
> 
>     printf("Removing named shared memory block...");
>     rv = apr_shm_remove(SHARED_FILENAME, pool);
>     if (rv != APR_SUCCESS) {
>         fprintf(stderr, "Error removing shared memory block\n");
>         return rv;
>     }
>     fprintf(stdout, "OK\n");
> 
>     printf("Creating named shared memory block second time(%"
>            APR_SIZE_T_FMT " bytes)........", SHARED_SIZE);
>     rv = apr_shm_create(&shm, SHARED_SIZE, SHARED_FILENAME, pool);
>     if (rv != APR_SUCCESS) {
>         fprintf(stderr, "Error allocating shared memory block\n");
>         return rv;
>     }
>     fprintf(stdout, "OK\n");
> 
>     printf("Destroying shared memory segment...");
>     rv = apr_shm_destroy(shm);
>     if (rv != APR_SUCCESS) {
>         printf("FAILED\n");
>         return rv;
>     }
>     printf("OK\n");
>     
>     return APR_SUCCESS; 
> }
> 
284a335,341
> 
>     if ((rv = test_named_remove(pool)) != APR_SUCCESS) {
>         printf("Name-based shared memory remove test FAILED: [%d] %s \n",
>                rv, apr_strerror(rv, errmsg, sizeof(errmsg)));
>         exit(-3);
>     }
>     printf("Named shared memory removal test passed!\n");

Reply via email to