aaron 02/01/16 14:16:30
Modified: shmem/unix shm.c
Log:
Fix a bug in the APR_USE_SHMEM_SHMGET type of name-based shared
memory. When a segment has been marked for deletion, other processes
are not allowed to attach to that segment.
This also fixes the problem with the name-based portion of the testshm.c
test.
Revision Changes Path
1.6 +18 -22 apr/shmem/unix/shm.c
Index: shm.c
===================================================================
RCS file: /home/cvs/apr/shmem/unix/shm.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- shm.c 16 Jan 2002 21:37:19 -0000 1.5
+++ shm.c 16 Jan 2002 22:16:30 -0000 1.6
@@ -78,7 +78,6 @@
#if APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
apr_size_t nbytes;
apr_file_t *file; /* file where metadata is stored */
- int shmid;
#endif
/* FIXME: associate this thing with a pool and set up a destructor
@@ -152,31 +151,32 @@
new_m->realsize = reqsize;
new_m->filename = NULL;
- if ((shmid = shmget(IPC_PRIVATE, new_m->realsize,
- SHM_R | SHM_W | IPC_CREAT)) < 0) {
+ if ((new_m->shmid = shmget(IPC_PRIVATE, new_m->realsize,
+ SHM_R | SHM_W | IPC_CREAT)) < 0) {
return errno;
}
- if ((new_m->base = shmat(shmid, NULL, 0)) == (void *)-1) {
+ if ((new_m->base = shmat(new_m->shmid, NULL, 0)) == (void *)-1) {
return errno;
}
new_m->usable = new_m->base;
- if (shmctl(shmid, IPC_STAT, &shmbuf) == -1) {
+ if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
return errno;
}
apr_current_userid(&uid, &gid, pool);
shmbuf.shm_perm.uid = uid;
shmbuf.shm_perm.gid = gid;
- if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
+ if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
return errno;
}
- new_m->shmid = shmid;
-
- /* Remove the segment once use count hits zero. */
- if (shmctl(shmid, IPC_RMID, NULL) == -1) {
+ /* 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(new_m->shmid, IPC_RMID, NULL) == -1) {
return errno;
}
@@ -257,27 +257,25 @@
#if APR_USE_SHMEM_SHMGET
new_m->realsize = reqsize;
- if ((shmid = shmget(ftok(filename, 1), new_m->realsize,
- SHM_R | SHM_W | IPC_CREAT)) < 0) {
+ if ((new_m->shmid = shmget(ftok(filename, 1), new_m->realsize,
+ SHM_R | SHM_W | IPC_CREAT)) < 0) {
return errno;
}
- new_m->base = shmat(shmid, NULL, 0);
+ new_m->base = shmat(new_m->shmid, NULL, 0);
/* FIXME: Handle errors. */
new_m->usable = new_m->base;
- if (shmctl(shmid, IPC_STAT, &shmbuf) == -1) {
+ if (shmctl(new_m->shmid, IPC_STAT, &shmbuf) == -1) {
return errno;
}
apr_current_userid(&uid, &gid, pool);
shmbuf.shm_perm.uid = uid;
shmbuf.shm_perm.gid = gid;
- if (shmctl(shmid, IPC_SET, &shmbuf) == -1) {
+ if (shmctl(new_m->shmid, IPC_SET, &shmbuf) == -1) {
return errno;
}
- new_m->shmid = shmid;
-
/* FIXME: APR_OS_DEFAULT is too permissive, switch to 600 I think. */
status = apr_file_open(&file, filename,
APR_WRITE | APR_CREATE,
@@ -297,11 +295,6 @@
return status;
}
- /* Remove the segment once use count hits zero. */
- if (shmctl(shmid, IPC_RMID, NULL) == -1) {
- return errno;
- }
-
*m = new_m;
return APR_SUCCESS;
@@ -321,6 +314,9 @@
#elif APR_USE_SHMEM_MMAP_ANON
munmap(m->base, m->realsize);
#elif APR_USE_SHMEM_SHMGET || APR_USE_SHMEM_SHMGET_ANON
+ if (shmctl(m->shmid, IPC_RMID, NULL) == -1) {
+ return errno;
+ }
shmdt(m->base);
#endif