diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2011-01-11 20:34:00 -0500 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2011-01-11 20:34:00 -0500 |
commit | 6a98bb0028df6243d40ce538324305498870e66f (patch) | |
tree | f44aff3891d8cf0226f67f8eae2933353a7b4129 /serial.c | |
parent | 409ab1d850e41c8f029b3fd91b02b1be15a367a8 (diff) | |
download | gpsd-6a98bb0028df6243d40ce538324305498870e66f.tar.gz |
Re-commit the new device locking, previously removed by a finger error.
Diffstat (limited to 'serial.c')
-rw-r--r-- | serial.c | 57 |
1 files changed, 34 insertions, 23 deletions
@@ -72,12 +72,13 @@ static sourcetype_t gpsd_classify(const char *path) #include <dirent.h> #include <ctype.h> -static bool anyopen(const char *path) +static int fusercount(const char *path) /* return true if any process has the specified path open */ { DIR *procd, *fdd; struct dirent *procentry, *fdentry; char procpath[32], fdpath[64], linkpath[64]; + int cnt = 0; if ((procd = opendir("/proc")) == NULL) return false; @@ -95,16 +96,15 @@ static bool anyopen(const char *path) if (readlink(fdpath, linkpath, sizeof(linkpath)) == -1) continue; if (strcmp(linkpath, path) == 0) { - (void)closedir(fdd); (void)closedir(procd); return true; } } + (void)closedir(fdd); } - - (void)closedir(fdd); (void)closedir(procd); - return false; + + return cnt; } #endif /* __linux__ */ @@ -375,20 +375,6 @@ int gpsd_open(struct gps_device_t *session) } else #endif /* BLUEZ */ { -#ifdef __linux__ - /* - * Don't touch devices already opened by another process. We - * have to make an exception for ptys, which are intentionally - * opened by another process on the master side, otherwise we'll - * break all our regression tests. - */ - if (session->sourcetype != source_pty && anyopen(session->gpsdata.dev.path)) { - gpsd_report(LOG_ERROR, - "%s already opened by another process\n", - session->gpsdata.dev.path); - return -1; - } -#endif /* __linux__ */ if ((session->gpsdata.gps_fd = open(session->gpsdata.dev.path, (int)(mode | O_NONBLOCK | O_NOCTTY))) == -1) { @@ -408,11 +394,36 @@ int gpsd_open(struct gps_device_t *session) } /* - * Try to block other processes from using this device while we - * have it open (later opens should return EBUSY). Won't work - * against anything with root privileges, alas. + * Ideally we want to exclusion-lock the device before doing any reads. + * It would have been best to do this at open(2) time, but O_EXCL + * doesn't work wuthout O_CREAT. + * + * We have to make an exception for ptys, which are intentionally + * opened by another process on the master side, otherwise we'll + * break all our regression tests. */ - (void)ioctl(session->gpsdata.gps_fd, TIOCEXCL); + if (session->sourcetype != source_pty) { + /* + * Try to block other processes from using this device while we + * have it open (later opens should return EBUSY). Won't work + * against anything with root privileges, alas. + */ + (void)ioctl(session->gpsdata.gps_fd, TIOCEXCL); + +#ifdef __linux__ + /* + * Don't touch devices already opened by another process. + */ + if (fusercount(session->gpsdata.dev.path) > 1) { + gpsd_report(LOG_ERROR, + "%s already opened by another process\n", + session->gpsdata.dev.path); + (void)close(session->gpsdata.gps_fd); + session->gpsdata.gps_fd = -1; + return -1; + } +#endif /* __linux__ */ + } #ifdef FIXED_PORT_SPEED session->saved_baud = FIXED_PORT_SPEED; |