diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2015-01-31 15:16:55 -0500 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2015-01-31 15:16:55 -0500 |
commit | 6ee9556f2fea231303a488f07a8b0e0a9f552dc4 (patch) | |
tree | 0427b34e9b53f0317b3c575ef5cd507bae92be35 | |
parent | 2bab8b2a7f810a4a430def430cbae80d74c572c6 (diff) | |
download | gpsd-6ee9556f2fea231303a488f07a8b0e0a9f552dc4.tar.gz |
Back out the attempt to use VTIME.
According to Matthias Drochner at
http://lists.lysator.liu.se/pipermail/lsh-bugs/2003q4/000151.html:
I thought I'd give lsh a try, just to see how it compares to openssh...
The client didn't work well on NetBSD, got a message like "unexpected
EWOULDBLOCK" on each keystroke.
Looked a bit deeper and found that stdin is set to O_NONBLOCK and
a raw tty mode with c_cc[VMIN] > 1 and c_cc[VTIME] > 0.
I'll append a little test program which does the same. I've tried
it on 3 operating systems (Linux, NetBSD, Digital UNIX), and it
behaves differently on each:
-on Linux, if a key is pressed, the read returns immediately with
that one character
-on NetBSD, the read returns with no data but EWOULDBLOCK
-on D'UNIX, the poll() doesn't teturn before 4 keypresses are done;
the read() returns these 4 characters
Indeed, in SUSv2's termios page is a sentence which says that if
both O_NONBLOCK and VTIME>0 are set, the behaviour is more or less
undefined.
I've solved my immediate problems by setting VMIN to 1 instead of 4
in unix_interact.c:do_make_raw(), but VTIME is still pointless,
so I wouldn't call this a clean solution.
All regression tests pass.
-rw-r--r-- | driver_evermore.c | 1 | ||||
-rw-r--r-- | driver_garmin.c | 3 | ||||
-rw-r--r-- | driver_geostar.c | 1 | ||||
-rw-r--r-- | driver_italk.c | 1 | ||||
-rw-r--r-- | driver_navcom.c | 1 | ||||
-rw-r--r-- | driver_nmea2000.c | 1 | ||||
-rw-r--r-- | driver_oncore.c | 1 | ||||
-rw-r--r-- | driver_proto.c | 2 | ||||
-rw-r--r-- | driver_sirf.c | 1 | ||||
-rw-r--r-- | driver_superstar2.c | 1 | ||||
-rw-r--r-- | driver_tsip.c | 1 | ||||
-rw-r--r-- | driver_ubx.c | 1 | ||||
-rw-r--r-- | driver_zodiac.c | 1 | ||||
-rw-r--r-- | drivers.c | 19 | ||||
-rw-r--r-- | gpsd.h-tail | 2 | ||||
-rw-r--r-- | gpsdecode.c | 2 | ||||
-rw-r--r-- | libgpsd_core.c | 3 | ||||
-rw-r--r-- | serial.c | 69 |
18 files changed, 14 insertions, 97 deletions
diff --git a/driver_evermore.c b/driver_evermore.c index 92a99044..132d1db4 100644 --- a/driver_evermore.c +++ b/driver_evermore.c @@ -637,7 +637,6 @@ const struct gps_type_t driver_evermore = #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 10, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ #endif /* defined(EVERMORE_ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_garmin.c b/driver_garmin.c index 7450d5f7..d9d4888d 100644 --- a/driver_garmin.c +++ b/driver_garmin.c @@ -1401,7 +1401,6 @@ const struct gps_type_t driver_garmin_usb_binary_old = #ifdef TIMEHINT_ENABLE .time_offset = garmin_time_offset, #endif /* TIMEHINT_ENABLE */ - .minlength = 0; /* min packet length unknown */ }; /* *INDENT-ON* */ #endif /* __UNUSED__ */ @@ -1432,7 +1431,6 @@ const struct gps_type_t driver_garmin_usb_binary = #ifdef TIMEHINT_ENABLE .time_offset = garmin_time_offset, #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* min packet length unknown */ }; /* *INDENT-ON* */ @@ -1462,7 +1460,6 @@ const struct gps_type_t driver_garmin_ser_binary = #ifdef TIMEHINT_ENABLE .time_offset = garmin_time_offset, #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* min packet length unknown */ }; /* *INDENT-ON* */ diff --git a/driver_geostar.c b/driver_geostar.c index 06b2d563..11e9ad78 100644 --- a/driver_geostar.c +++ b/driver_geostar.c @@ -640,7 +640,6 @@ const struct gps_type_t driver_geostar = #ifdef TIMEHINT_ENABLE .time_offset = geostar_time_offset, #endif /* TIMEHINT_ENABLE */ - .minlength = 24, /* min packet length for the GeoStar */ }; /* *INDENT-ON* */ diff --git a/driver_italk.c b/driver_italk.c index e1cdf483..051376c2 100644 --- a/driver_italk.c +++ b/driver_italk.c @@ -432,7 +432,6 @@ const struct gps_type_t driver_italk = #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 30, /* min packet length for chunked output */ }; /* *INDENT-ON* */ #endif /* defined(ITRAX_ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_navcom.c b/driver_navcom.c index 067aef0b..925b7b61 100644 --- a/driver_navcom.c +++ b/driver_navcom.c @@ -1310,7 +1310,6 @@ const struct gps_type_t driver_navcom = #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 10, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ diff --git a/driver_nmea2000.c b/driver_nmea2000.c index 4059dbee..d74233b4 100644 --- a/driver_nmea2000.c +++ b/driver_nmea2000.c @@ -1700,7 +1700,6 @@ const struct gps_type_t driver_nmea2000 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* min packet length unknown */ }; /* *INDENT-ON* */ diff --git a/driver_oncore.c b/driver_oncore.c index 569e1f4d..8cea6e7c 100644 --- a/driver_oncore.c +++ b/driver_oncore.c @@ -520,7 +520,6 @@ const struct gps_type_t driver_oncore = { #ifdef TIMEHINT_ENABLE .time_offset = oncore_time_offset, /* NTP offset array */ #endif /* TIMEHINT_ENABLE */ - .minlength = 38, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ #endif /* defined(ONCORE_ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_proto.c b/driver_proto.c index e8953cf8..bbbd7c0d 100644 --- a/driver_proto.c +++ b/driver_proto.c @@ -533,8 +533,6 @@ const struct gps_type_t driver__proto__binary = { #ifdef TIMEHINT_ENABLE .time_offset = _proto_time_offset, #endif /* TIMEHINT_ENABLE */ - /* minimum length of packet, used for I/O optimization */ - .minlength = 0; /* *INDENT-ON* */ }; #endif /* defined(_PROTO__ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_sirf.c b/driver_sirf.c index 87146ce7..20e7b513 100644 --- a/driver_sirf.c +++ b/driver_sirf.c @@ -1590,7 +1590,6 @@ const struct gps_type_t driver_sirf = #ifdef TIMEHINT_ENABLE .time_offset = sirf_time_offset, #endif /* NTP_SHM_ENABLE */ - .minlength = 13, /* minimum SiRF packet length */ }; /* *INDENT-ON* */ #endif /* defined(SIRF_ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_superstar2.c b/driver_superstar2.c index 95d69cd4..94cc3320 100644 --- a/driver_superstar2.c +++ b/driver_superstar2.c @@ -585,7 +585,6 @@ const struct gps_type_t driver_superstar2 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 65, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ #endif /* defined(SUPERSTAR2_ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_tsip.c b/driver_tsip.c index 994da718..6134e3d9 100644 --- a/driver_tsip.c +++ b/driver_tsip.c @@ -1281,7 +1281,6 @@ const struct gps_type_t driver_tsip = #ifdef TIMEHINT_ENABLE .time_offset = tsip_time_offset, #endif /* TIMEHINT_ENABLE */ - .minlength = 5, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ diff --git a/driver_ubx.c b/driver_ubx.c index 260c8523..2f2a7358 100644 --- a/driver_ubx.c +++ b/driver_ubx.c @@ -992,7 +992,6 @@ const struct gps_type_t driver_ubx = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 17, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ #endif /* defined(UBLOX_ENABLE) && defined(BINARY_ENABLE) */ diff --git a/driver_zodiac.c b/driver_zodiac.c index 1da18bf4..2a0e367e 100644 --- a/driver_zodiac.c +++ b/driver_zodiac.c @@ -486,7 +486,6 @@ const struct gps_type_t driver_zodiac = #ifdef TIMEHINT_ENABLE .time_offset = zodiac_time_offset, /* compute NTO fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 40, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ @@ -16,8 +16,6 @@ #include "bits.h" /* for getbeu16(), to extract big-endian words */ #include "strfuncs.h" -#define NMEA_MINLENGTH 16 /* minimum length of NMEA0183 packet */ - ssize_t generic_get(struct gps_device_t *session) { return packet_get(session->gpsdata.gps_fd, &session->lexer); @@ -104,7 +102,6 @@ const struct gps_type_t driver_unknown = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* minimum packet length is unknown */ }; /* *INDENT-ON* */ @@ -275,7 +272,6 @@ const struct gps_type_t driver_nmea0183 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ @@ -378,7 +374,6 @@ const struct gps_type_t driver_garmin = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* min packet length for chunked I/O */ }; /* *INDENT-ON* */ #endif /* GARMIN_ENABLE && NMEA_ENABLE */ @@ -442,7 +437,6 @@ const struct gps_type_t driver_ashtech = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* minimum packet length is unknown */ }; /* *INDENT-ON* */ #endif /* ASHTECH_ENABLE */ @@ -495,7 +489,6 @@ const struct gps_type_t driver_fv18 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NMEA minimum length */ }; /* *INDENT-ON* */ #endif /* FV18_ENABLE */ @@ -551,7 +544,6 @@ const struct gps_type_t driver_gpsclock = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NMEA minimum length */ }; /* *INDENT-ON* */ #endif /* GPSCLOCK_ENABLE */ @@ -608,7 +600,6 @@ static const struct gps_type_t driver_tripmate = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NME0183 minimum langth */ }; /* *INDENT-ON* */ #endif /* TRIPMATE_ENABLE */ @@ -660,7 +651,6 @@ static const struct gps_type_t driver_earthmate = { #endif /* CONTROLSEND_ENABLE */ #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ - .minlength = 40, /* use Zodiac minimum langth */ #endif /* TIMEHINT_ENABLE */ }; /*@ -redef @*/ @@ -788,7 +778,6 @@ const struct gps_type_t driver_trueNorth = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NME0183 minimum langth */ }; /* *INDENT-ON* */ #endif @@ -869,7 +858,6 @@ static const struct gps_type_t driver_oceanServer = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NME0183 minimum langth */ }; /* *INDENT-ON* */ #endif @@ -938,7 +926,6 @@ static const struct gps_type_t driver_fury = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NME0183 minimum langth */ }; /* *INDENT-ON* */ @@ -994,7 +981,6 @@ static const struct gps_type_t driver_rtcm104v2 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* raw I/O - could probably be tuned */ }; /* *INDENT-ON* */ #endif /* RTCM104V2_ENABLE */ @@ -1042,7 +1028,6 @@ static const struct gps_type_t driver_rtcm104v3 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* raw I/O - could probably be tuned */ }; /* *INDENT-ON* */ #endif /* RTCM104V3_ENABLE */ @@ -1079,7 +1064,6 @@ static const struct gps_type_t driver_garmintxt = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = 0, /* min packet length unknown */ }; /* *INDENT-ON* */ #endif /* GARMINTXT_ENABLE */ @@ -1176,7 +1160,6 @@ const struct gps_type_t driver_mtk3301 = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, #endif /* TIMEHINT_ENABLE */ - .minlength = NMEA_MINLENGTH, /* use NME0183 minimum langth */ }; /* *INDENT-ON* */ #endif /* MTK3301_ENABLE */ @@ -1420,7 +1403,6 @@ const struct gps_type_t driver_aivdm = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no NTP communication */ #endif /* TIMEHINT_ENABLE */ - .minlength = 23, /* minimum AIVDM packet length */ }; /* *INDENT-ON* */ #endif /* AIVDM_ENABLE */ @@ -1525,7 +1507,6 @@ const struct gps_type_t driver_json_passthrough = { #ifdef TIMEHINT_ENABLE .time_offset = NULL, /* no method for NTP fudge factor */ #endif /* TIMEHINT_ENABLE */ - .minlength = 43, /* minimum JSON packet length */ }; /* *INDENT-ON* */ diff --git a/gpsd.h-tail b/gpsd.h-tail index edc8930f..8cdf1761 100644 --- a/gpsd.h-tail +++ b/gpsd.h-tail @@ -389,7 +389,6 @@ struct gps_type_t { #ifdef TIMEHINT_ENABLE /*@null@*/double (*time_offset)(struct gps_device_t *session); #endif /* TIMEHINT_ENABLE */ - int minlength; }; /* @@ -824,7 +823,6 @@ extern void ntrip_report(struct gps_context_t *, extern void gpsd_tty_init(struct gps_device_t *); extern int gpsd_serial_open(struct gps_device_t *); -extern void gpsd_optimize_io(struct gps_device_t *, const int, const bool); extern bool gpsd_set_raw(struct gps_device_t *); extern ssize_t gpsd_serial_write(struct gps_device_t *, const char *, const size_t); diff --git a/gpsdecode.c b/gpsdecode.c index ece81d57..f31a59f6 100644 --- a/gpsdecode.c +++ b/gpsdecode.c @@ -621,7 +621,7 @@ static void decode(FILE *fpin, FILE*fpout) break; } } - printf("%s (%d): %u\n", np, i-1, (unsigned int)minima[i]); + printf("%s (%d): %d\n", np, i-1, (unsigned int)minima[i]); } } } diff --git a/libgpsd_core.c b/libgpsd_core.c index 579d32e1..b9868bfa 100644 --- a/libgpsd_core.c +++ b/libgpsd_core.c @@ -248,9 +248,6 @@ int gpsd_switch_driver(struct gps_device_t *session, char *type_name) "selecting %s driver...\n", (*dp)->type_name); gpsd_assert_sync(session); - gpsd_optimize_io(session, - (*dp)->minlength, - TEXTUAL_PACKET_TYPE((*dp)->packet_type)); /*@i@*/ session->device_type = *dp; session->driver_index = i; #ifdef RECONFIGURE_ENABLE @@ -535,7 +535,19 @@ int gpsd_serial_open(struct gps_device_t *session) &session->ttyset_old, sizeof(session->ttyset)); /* * Only block until we get at least one character, whatever the - * third arg of read(2) says. + * third arg of read(2) says. According to + * http://stackoverflow.com/questions/20154157/termios-vmin-vtime-and-blocking-non-blocking-read-operations + * the VMIN setting may be a no-op because the tty was opened with + * O_NONBLOCK. Money quote: + * + * "When using select() with a file in non-blocking mode, you + * get an event for every byte that arrives. At high serial + * data rates, this hammers the CPU. It's better to use + * blocking mode with VMIN, so that select() waits for a + * block of data before firing an event, and VTIME to limit + * the delay, for blocks smaller than VMIN." + * + * Would that we could do the latter... */ /*@ ignore @*/ memset(session->ttyset.c_cc, 0, sizeof(session->ttyset.c_cc)); @@ -609,61 +621,6 @@ ssize_t gpsd_serial_write(struct gps_device_t * session, return status; } -void gpsd_optimize_io(struct gps_device_t *session, - int minlength, const bool textual UNUSED) -/* optimize I/O mode depending on the minimum packet size */ -{ - /* bail out if this is not actually a tty */ - if (isatty(session->gpsdata.gps_fd) == 0) - return; - -#ifdef __NetBSD__ - /* - * Apparently NetBSD termios (at least on pty on netbsd-[56]) has - * trouble with VMIN=n VTIME=1. Or reads are aftempted when no - * bytes are present and none arrive, in which case read is - * correct for waiting indefinitely. Until this is - * debugged/fixed, avoid it, because even if it doesn't affect - * actual operation (unknown) it's important to preserve - * regression tests to allow bisecting for other bugs. - * http://pubs.opengroup.org/onlinepubs/007908799/xbd/termios.html - */ - minlength = 1; -#endif - - /* - * This is an optimization hack. The idea is to get away from - * character-at-a-time I/O in order to slow down the rate at - * which the main select loop spins (those calls eat power - * noticeably in environments like Android phones and the - * Raspberry Pi). We tell the tty layer to wait until it has - * either accumulated characters corresponding to the minimum - * possible length of a packet or timed out. - * - * For the moment, we do nothing with the textual flag. We'd like - * to use it to set ICANON mode and let the kernel do all the line - * buffering itself. The problem with this is that VTIME stops - * working in ICANON mode, so a binary packet coming up the wire - * would result in no further input being seen. - */ - if (minlength > 1) { - session->ttyset.c_cc[VMIN] = minlength; - session->ttyset.c_cc[VTIME] = 1; /* 0.1 sec */ - } else { - /* raw character-at-at-time I/O, no timeout */ - session->ttyset.c_cc[VMIN] = 1; - session->ttyset.c_cc[VTIME] = 0; - } - - if (tcsetattr(session->gpsdata.gps_fd, TCSANOW, &session->ttyset) != 0) - return; - - gpsd_report(&session->context->errout, LOG_IO, - "tty params optimized for min length %d of %s packets\n", - minlength, textual ? "textual" : "binary"); -} - - /* * This constant controls how long the packet sniffer will spend looking * for a packet leader before it gives up. It *must* be larger than |