summaryrefslogtreecommitdiff
path: root/shmexport.c
diff options
context:
space:
mode:
authorFred Wright <fw@fwright.net>2017-03-23 20:27:33 -0700
committerFred Wright <fw@fwright.net>2017-03-24 15:48:44 -0700
commit4ee196cd9c34f7a268118d4088392e392546fe42 (patch)
tree077adb566143d8a69436085a3f7b39f1726187f9 /shmexport.c
parent2bb3d4973597d3aa0f4376ce7191d09299f40cc0 (diff)
downloadgpsd-4ee196cd9c34f7a268118d4088392e392546fe42.tar.gz
Fixes broken 'GPSD' SHM export.
Commit 22c3faf added an IPC_RMID operation right after the shmat(), in order to keep the segment from lingering after gpsd exits. But this clears the key, making it impossible for a client to attach to the segment. This fix moves the IPC_RMID to shm_release(), so that it's not invoked until gpsd is done with the segment. This required saving the shmid in the gps_context structure. TESTED: On both OSX and Linux, used ipcs to verify that the segment is present with the correct ID while gpsd is running, and disappears after gpsd exits. Also verified that warning message for shmctl() appears when two gpsds conflict over the SHM segment.
Diffstat (limited to 'shmexport.c')
-rw-r--r--shmexport.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/shmexport.c b/shmexport.c
index 2edf0776..806b85c2 100644
--- a/shmexport.c
+++ b/shmexport.c
@@ -37,7 +37,6 @@ PERMISSIONS
bool shm_acquire(struct gps_context_t *context)
/* initialize the shared-memory segment to be used for export */
{
- int status;
long shmkey = getenv("GPSD_SHM_KEY") ? strtol(getenv("GPSD_SHM_KEY"), NULL, 0) : GPSD_SHM_KEY;
int shmid = shmget((key_t)shmkey, sizeof(struct shmexport_t), (int)(IPC_CREAT|0666));
@@ -61,16 +60,7 @@ bool shm_acquire(struct gps_context_t *context)
context->shmexport = NULL;
return false;
}
- /* mark shmid to go away when no longer used
- * Having it linger forever is bad, and when the size enlarges
- * it can no longer be opened */
- status = shmctl(shmid, IPC_RMID, NULL);
- if (status == -1) {
- gpsd_log(&context->errout, LOG_ERROR,
- "shmctl failed, errno = %d (%s)\n",
- errno, strerror(errno));
- exit(1);
- }
+ context->shmid = shmid;
gpsd_log(&context->errout, LOG_PROG,
"shmat() for SHM export succeeded, segment %d\n", shmid);
@@ -80,8 +70,19 @@ bool shm_acquire(struct gps_context_t *context)
void shm_release(struct gps_context_t *context)
/* release the shared-memory segment used for export */
{
- if (context->shmexport != NULL)
- (void)shmdt((const void *)context->shmexport);
+ if (context->shmexport == NULL)
+ return;
+
+ /* Mark shmid to go away when no longer used
+ * Having it linger forever is bad, and when the size enlarges
+ * it can no longer be opened
+ */
+ if (shmctl(context->shmid, IPC_RMID, NULL) == -1) {
+ gpsd_log(&context->errout, LOG_WARN,
+ "shmctl for IPC_RMID failed, errno = %d (%s)\n",
+ errno, strerror(errno));
+ }
+ (void)shmdt((const void *)context->shmexport);
}
void shm_update(struct gps_context_t *context, struct gps_data_t *gpsdata)