- 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");
