summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gpsd.c8
-rw-r--r--gpsd.h-tail2
-rw-r--r--ntpshm.c45
3 files changed, 55 insertions, 0 deletions
diff --git a/gpsd.c b/gpsd.c
index aeb31a06..c42ad38d 100644
--- a/gpsd.c
+++ b/gpsd.c
@@ -1984,6 +1984,14 @@ int main(int argc, char *argv[])
}
}
+#if defined(HAVE_SYS_TIMEPPS_H)
+ /*
+ * Wait here until all the thread spawns produced by opening command-line
+ * PPS devices no longer need root privileges.
+ */
+ gpsd_await_pps_initialization()
+#endif /* defined(HAVE_SYS_TIMEPPS_H) */
+
/* drop privileges */
if (getuid() == 0) {
struct passwd *pw;
diff --git a/gpsd.h-tail b/gpsd.h-tail
index 9c22d8d3..0150f31b 100644
--- a/gpsd.h-tail
+++ b/gpsd.h-tail
@@ -799,6 +799,8 @@ extern void ntpshm_init(struct gps_context_t *, bool);
extern int ntpshm_put(struct gps_device_t *, double, double);
extern void ntpd_link_deactivate(struct gps_device_t *);
extern void ntpd_link_activate(struct gps_device_t *);
+extern void gpsd_await_pps_initialization(void);
+
extern void ecef_to_wgs84fix(/*@out@*/struct gps_fix_t *,
/*@out@*/double *,
diff --git a/ntpshm.c b/ntpshm.c
index a757d36d..3a46a38e 100644
--- a/ntpshm.c
+++ b/ntpshm.c
@@ -31,6 +31,11 @@
#include <sys/ipc.h>
#include <sys/shm.h>
+#if defined(HAVE_SYS_TIMEPPS_H)
+static pthread_mutex_t initialization_mutex;
+static int uninitialized_pps_thread_count;
+#endif /* defined(HAVE_SYS_TIMEPPS_H) */
+
#define PPS_MAX_OFFSET 100000 /* microseconds the PPS can 'pull' */
#define PUT_MAX_OFFSET 1000000 /* microseconds for lost lock */
@@ -523,6 +528,14 @@ static int init_kernel_pps(struct gps_device_t *session) {
}
/* root privs are not required past this point */
+ /*@ -unrecog (splint has no pthread declarations as yet) @*/
+ (void)pthread_mutex_lock(&initialization_mutex);
+ /* +unrecog */
+ --uninitialized_pps_thread_count;
+ /*@ -unrecog (splint has no pthread declarations as yet) @*/
+ (void)pthread_mutex_unlock(&initialization_mutex);
+ /* +unrecog */
+
if ( 0 > time_pps_create(ret, &session->kernelpps_handle )) {
gpsd_report(session->context->debug, LOG_INF,
"KPPS time_pps_create(%d) failed: %s\n",
@@ -553,6 +566,29 @@ static int init_kernel_pps(struct gps_device_t *session) {
}
return 0;
}
+
+void gpsd_await_pps_initialization(void)
+/* wait for all threads seeking kernel PPS to open /dev/pps devuces */
+{
+ /* wait only this many sec if some thread croaked too early */
+ static int dropdead = 10;
+
+ gpsd_report(session->context->debug, LOG_WARN,
+ "waiting on KPPS initalization...\n");
+
+ while (dropdead > 0)
+ {
+ /*@ -unrecog (splint has no pthread declarations as yet) @*/
+ (void)pthread_mutex_lock(&initialization_mutex);
+ /* +unrecog */
+ if (uninitialized_pps_thread_count == 0)
+ return
+ /*@ -unrecog (splint has no pthread declarations as yet) @*/
+ (void)pthread_mutex_unlock(&initialization_mutex);
+ /* +unrecog */
+ usleep(1000)
+ }
+}
#endif /* defined(HAVE_SYS_TIMEPPS_H) */
volatile bool gpsd_ppsmonitor_stop = false;
@@ -976,6 +1012,15 @@ static void pps_thread_activate(struct gps_device_t *session)
pthread_t pt;
if (session->shmTimeP >= 0) {
gpsd_report(session->context->debug, LOG_PROG, "PPS thread launched\n");
+#if defined(HAVE_SYS_TIMEPPS_H)
+ /*@ -unrecog (splint has no pthread declarations as yet) @*/
+ (void)pthread_mutex_lock(&initialization_mutex);
+ /* +unrecog */
+ ++uninitialized_pps_thread_count;
+ /*@ -unrecog (splint has no pthread declarations as yet) @*/
+ (void)pthread_mutex_unlock(&initialization_mutex);
+ /* +unrecog */
+#endif /* defined(HAVE_SYS_TIMEPPS_H) */
/*@-compdef -nullpass@*/
(void)pthread_create(&pt, NULL, gpsd_ppsmonitor, (void *)session);
/*@+compdef +nullpass@*/