diff options
-rw-r--r-- | gpsd.c | 8 | ||||
-rw-r--r-- | gpsd.h-tail | 2 | ||||
-rw-r--r-- | ntpshm.c | 45 |
3 files changed, 55 insertions, 0 deletions
@@ -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 *, @@ -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@*/ |