summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWolfgang Ocker <weo@reccoware.de>2014-05-17 08:39:00 -0400
committerEric S. Raymond <esr@thyrsus.com>2014-05-17 08:39:00 -0400
commit9c6ba55f453eddc7938181332c743c5ae4d18550 (patch)
tree4863d92b71760d8bdb4fd5648d57f472a08c5bc1
parent243ce14f30abf4f559c986b9459ff1bd1ec6da88 (diff)
downloadgpsd-9c6ba55f453eddc7938181332c743c5ae4d18550.tar.gz
Accesses to subscriber_t->fd should be synchronized
Otherwise, FD_ISSET(sub->fd, ...) might crash since sub->fd might have set to -1 in detach_client() called by ppsthread or main loop Signed-off-by: Wolfgang Ocker <weo@reccoware.de>
-rw-r--r--gpsd.c26
1 files changed, 24 insertions, 2 deletions
diff --git a/gpsd.c b/gpsd.c
index a3c68236..bb71c7d4 100644
--- a/gpsd.c
+++ b/gpsd.c
@@ -536,6 +536,7 @@ struct subscriber_t
int fd; /* client file descriptor. -1 if unused */
timestamp_t active; /* when subscriber last polled for data */
struct policy_t policy; /* configurable bits */
+ pthread_mutex_t mutex; /* serialize access to fd */
};
#ifdef LIMITED_MAX_CLIENTS
@@ -551,6 +552,16 @@ static struct subscriber_t subscribers[MAXSUBSCRIBERS]; /* indexed by client fil
#define UNALLOCATED_FD -1
+static void lock_subscriber(struct subscriber_t *sub)
+{
+ (void)pthread_mutex_lock(&sub->mutex);
+}
+
+static void unlock_subscriber(struct subscriber_t *sub)
+{
+ (void)pthread_mutex_unlock(&sub->mutex);
+}
+
static /*@null@*//*@observer@ */ struct subscriber_t *allocate_client(void)
/* return the address of a subscriber structure allocated for a new session */
{
@@ -572,8 +583,11 @@ static void detach_client(struct subscriber_t *sub)
/* detach a client and terminate the session */
{
char *c_ip;
- if (sub->fd == UNALLOCATED_FD)
+ lock_subscriber(sub);
+ if (sub->fd == UNALLOCATED_FD) {
+ unlock_subscriber(sub);
return;
+ }
c_ip = netlib_sock2ip(sub->fd);
(void)shutdown(sub->fd, SHUT_RDWR);
gpsd_report(context.debug, LOG_SPIN,
@@ -595,6 +609,7 @@ static void detach_client(struct subscriber_t *sub)
sub->policy.split24 = false;
sub->policy.devpath[0] = '\0';
sub->fd = UNALLOCATED_FD;
+ unlock_subscriber(sub);
/*@+mustfreeonly@*/
}
@@ -2111,8 +2126,10 @@ int main(int argc, char *argv[])
"running with effective user ID %d\n", geteuid());
#ifdef SOCKET_EXPORT_ENABLE
- for (i = 0; i < NITEMS(subscribers); i++)
+ for (i = 0; i < NITEMS(subscribers); i++) {
subscribers[i].fd = UNALLOCATED_FD;
+ (void)pthread_mutex_init(&subscribers[i].mutex, NULL);
+ }
#endif /* SOCKET_EXPORT_ENABLE*/
/*@-compdef -compdestroy@*/
@@ -2326,10 +2343,13 @@ int main(int argc, char *argv[])
if (sub->active == 0)
continue;
+ lock_subscriber(sub);
if (FD_ISSET(sub->fd, &rfds)) {
char buf[BUFSIZ];
int buflen;
+ unlock_subscriber(sub);
+
gpsd_report(context.debug, LOG_PROG,
"checking client(%d)\n",
sub_index(sub));
@@ -2354,6 +2374,8 @@ int main(int argc, char *argv[])
detach_client(sub);
}
} else {
+ unlock_subscriber(sub);
+
if (!sub->policy.watcher
&& timestamp() - sub->active > COMMAND_TIMEOUT) {
gpsd_report(context.debug, LOG_WARN,