diff options
author | Fred Wright <fw@fwright.net> | 2017-03-23 20:27:33 -0700 |
---|---|---|
committer | Fred Wright <fw@fwright.net> | 2017-03-24 15:48:44 -0700 |
commit | 4ee196cd9c34f7a268118d4088392e392546fe42 (patch) | |
tree | 077adb566143d8a69436085a3f7b39f1726187f9 /shmexport.c | |
parent | 2bb3d4973597d3aa0f4376ce7191d09299f40cc0 (diff) | |
download | gpsd-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.c | 27 |
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) |