In regards to c programming with select() on linux. The function that
is giving me trouble tries to mimic a select call while also waiting
for third party data to arrive from a gps device. The library
interfacing with the usb gps via libusb has been heavily debugged and
is not the culprit in this case. The library incorporates a
read/write buffer within a thread which checks for data on the
interrupt in endpoint of the usb device. The function is as follows:
int em_select(int n, fd_set *readfds, fd_set *writefds, fd_set
*exceptfds, struct timeval *timeout)
{
struct timeval tv, curtime, endtime;
int count_fdschanged = 0;
fd_set rfds, wfds, efds;
int ret = 0;
/* writing to em buffer can never block (or reading for that matter)
* so the read buffer is checked for data before hitting the select call
*/
if (timeout) {
gettimeofday(&curtime, NULL);
gettimeofday(&endtime, NULL);
endtime.tv_sec += timeout->tv_sec;
endtime.tv_usec += timeout->tv_usec;
}
while (1) {
if (timeout) {
if ((curtime.tv_sec >= endtime.tv_sec) && (curtime.tv_usec >= endtime.tv_usec))
break;
}
if (em_read_data_avail())
count_fdschanged++;
if (count_fdschanged > 0)
break;
if (readfds)
//memcpy((char *)&rfds, (char *)readfds, sizeof(rfds));
rfds = *readfds;
if (writefds)
//memcpy((char *)&wfds, (char *)writefds, sizeof(wfds));
wfds = *writefds;
if (exceptfds)
//memcpy((char *)&efds, (char *)exceptfds, sizeof(efds));
efds = *exceptfds;
tv.tv_sec = 0;
tv.tv_usec = 25;
ret = select(n, (readfds ? &rfds : NULL), (writefds ? &wfds : NULL),
(exceptfds ? &efds : NULL), &tv);
if (ret<0)
goto quit;
else if (ret > 0)
count_fdschanged+=ret;
if (count_fdschanged > 0)
break;
if (timeout)
gettimeofday(&curtime, NULL);
}
ret = count_fdschanged;
quit:
if (readfds)
//memcpy((char *)readfds, (char *)&rfds, sizeof(rfds));
*readfds = rfds;
if (writefds)
//memcpy((char *)writefds, (char *)&wfds, sizeof(wfds));
*writefds = wfds;
if (exceptfds)
//memcpy((char *)exceptfds, (char *)&efds, sizeof(efds));
*exceptfds = efds;
return ret;
}
em_read_data_avail() is non-blocking - it returns the amount of data
in the read buffer. when polled quickly it will mostly return 0.
My problem: When an application uses this function, a call to
FD_ISSET() will return several bogus hits on the fd_set. This leads
me to believe that the fd_set is being corrupted in the above
function. The code segment can be found below:
if (FD_ISSET(fd, &rfds)) {
char buf[BUFSIZ];
int buflen;
gpsd_report(3, "checking %d \n", fd);
if ((buflen = read(fd, buf, sizeof(buf) - 1)) <= 0) {
(void) close(fd);
FD_CLR(fd, &all_fds);
FD_CLR(fd, &nmea_fds);
FD_CLR(fd, &watcher_fds);
} else {
buf[buflen] = '\0';
gpsd_report(1, "<= client: %s", buf);
session->poll_times[fd] = timestamp();
if (handle_request(fd, buf, buflen, 1) < 0) {
(void) close(fd);
FD_CLR(fd, &all_fds);
FD_CLR(fd, &nmea_fds);
FD_CLR(fd, &watcher_fds);
}
}
which is located towards the bottom of this source:
http://svn.berlios.de/viewcvs/gpsd/trunk/gpsd.c?rev=2053&view=markup
Here is some sample output from the gps daemon debug log:
gpsd: packet_sniff ends
gpsd: gpsd_activate: opened GPS (4)
gpsd: Selecting SiRF-II binary driver...
gpsd: Probing for firmware version...
gpsd: Writing SiRF control type 84: a0 a2 00 02 84 00 00 84 b0 b3
gpsd: checking 5
gpsd: <= client: gpsd: => client(5): GPSD
gpsd: Client write to 5: Invalid argument
gpsd: checking 7
gpsd: checking 10
gpsd: checking 12
gpsd: checking 14
gpsd: checking 18
gpsd: checking 30
gpsd: checking 46
gpsd: checking 50
gpsd: checking 62
gpsd: checking 67
gpsd: checking 69
gpsd: checking 70
gpsd: checking 71
gpsd: checking 73
gpsd: checking 75
gpsd: checking 76
gpsd: checking 77
gpsd: checking 78
gpsd: checking 79
gpsd: checking 82
gpsd: checking 91
gpsd: checking 96
gpsd: checking 133
gpsd: checking 134
gpsd: checking 136
gpsd: checking 139
gpsd: checking 140
gpsd: checking 141
gpsd: checking 143
gpsd: checking 144
gpsd: checking 146
gpsd: checking 147
gpsd: checking 148
gpsd: checking 149
gpsd: checking 150
gpsd: checking 151
gpsd: checking 152
gpsd: checking 153
gpsd: checking 154
gpsd: checking 155
gpsd: checking 156
gpsd: checking 157
gpsd: checking 159
gpsd: checking 160
gpsd: checking 164
gpsd: checking 166
gpsd: checking 168
gpsd: checking 169
gpsd: checking 172
gpsd: checking 176
gpsd: checking 178
gpsd: checking 190
gpsd: checking 198
gpsd: checking 199
gpsd: checking 204
gpsd: checking 213
gpsd: checking 222
gpsd: checking 226
gpsd: checking 228
gpsd: checking 229
gpsd: checking 230
gpsd: checking 231
gpsd: checking 232
gpsd: checking 233
gpsd: checking 234
gpsd: checking 235
gpsd: checking 245
gpsd: checking 254
gpsd: checking 258
gpsd: checking 259
gpsd: checking 260
gpsd: checking 261
gpsd: checking 262
gpsd: checking 264
gpsd: checking 267
gpsd: checking 268
gpsd: checking 269
gpsd: checking 271
gpsd: checking 272
gpsd: checking 274
gpsd: checking 275
gpsd: checking 276
gpsd: checking 277
gpsd: checking 278
gpsd: checking 279
gpsd: checking 280
gpsd: checking 281
gpsd: checking 282
gpsd: checking 283
gpsd: checking 284
gpsd: checking 285
gpsd: checking 287
gpsd: checking 289
gpsd: checking 290
gpsd: checking 291
gpsd: checking 292
gpsd: checking 294
gpsd: checking 296
gpsd: checking 297
gpsd: checking 298
gpsd: checking 302
gpsd: checking 304
gpsd: checking 306
gpsd: checking 318
gpsd: checking 324
gpsd: checking 325
gpsd: checking 327
gpsd: checking 332
gpsd: checking 341
gpsd: checking 350
gpsd: checking 357
gpsd: checking 361
gpsd: checking 363
gpsd: checking 366
gpsd: checking 367
gpsd: checking 368
gpsd: checking 369
gpsd: checking 371
gpsd: checking 372
gpsd: checking 382
gpsd: checking 386
gpsd: checking 388
gpsd: checking 389
gpsd: checking 390
gpsd: checking 391
gpsd: checking 392
gpsd: checking 393
gpsd: checking 394
gpsd: checking 395
gpsd: checking 397
gpsd: checking 399
gpsd: checking 400
gpsd: checking 401
gpsd: checking 403
gpsd: checking 404
gpsd: checking 414
gpsd: checking 416
gpsd: checking 420
gpsd: checking 450
gpsd: checking 452
gpsd: checking 453
gpsd: checking 455
gpsd: checking 456
gpsd: checking 457
gpsd: checking 458
gpsd: checking 459
gpsd: checking 460
gpsd: checking 462
gpsd: checking 464
gpsd: checking 478
gpsd: checking 483
gpsd: checking 485
gpsd: checking 486
gpsd: checking 487
gpsd: checking 490
gpsd: checking 493
gpsd: checking 494
gpsd: checking 496
gpsd: checking 510
gpsd: checking 512
gpsd: checking 550
gpsd: checking 551
gpsd: checking 552
gpsd: checking 555
gpsd: checking 556
gpsd: checking 557
gpsd: checking 559
gpsd: checking 560
gpsd: checking 562
gpsd: checking 563
gpsd: checking 564
gpsd: checking 565
gpsd: checking 566
gpsd: checking 567
gpsd: checking 568
gpsd: checking 569
gpsd: checking 570
gpsd: checking 571
gpsd: checking 572
gpsd: checking 573
gpsd: checking 575
gpsd: checking 577
gpsd: checking 581
gpsd: checking 583
gpsd: checking 585
gpsd: checking 586
gpsd: checking 588
gpsd: checking 589
gpsd: checking 591
gpsd: checking 606
gpsd: checking 610
gpsd: checking 612
gpsd: checking 615
gpsd: checking 617
gpsd: checking 618
gpsd: checking 621
gpsd: checking 622
gpsd: checking 624
gpsd: checking 638
gpsd: checking 672
gpsd: checking 704
gpsd: checking 804
gpsd: checking 806
gpsd: checking 809
gpsd: checking 810
gpsd: checking 812
gpsd: checking 814
gpsd: checking 815
gpsd: checking 818
gpsd: checking 827
gpsd: checking 832
gpsd: checking 835
gpsd: checking 864
gpsd: checking 866
gpsd: checking 867
gpsd: checking 870
gpsd: checking 872
gpsd: checking 875
gpsd: checking 879
gpsd: checking 882
gpsd: checking 891
gpsd: checking 899
gpsd: checking 901
gpsd: checking 903
gpsd: checking 906
gpsd: checking 908
gpsd: checking 910
gpsd: checking 914
gpsd: checking 926
gpsd: checking 928
gpsd: checking 929
(hangs at this point... no more output)
Killed
If any tips can be offered on how to fix this within the given
function 'em_select', or some other workaround, it would be much
appreciated. Thank you. |
Clarification of Question by
dignome-ga
on
20 Mar 2005 14:30 PST
Below is the edited portion of the code that calls em_select().
em_isemate() returns true if the gps daemon is set to use the
earthmate gps device, 0 if using normal tty:
for (;;) {
struct timeval tv;
memcpy((char *)&rfds, (char *)&all_fds, sizeof(rfds));
/*
* Poll for user commands or GPS data. The timeout doesn't
* actually matter here since select returns whenever one of
* the file descriptors in the set goes ready.
*/
tv.tv_sec = 1;
tv.tv_usec = 0;
if (em_isemate()) {
if (em_select(FD_SETSIZE, &rfds, NULL, NULL, &tv) < 0) {
if (errno == EINTR)
continue;
gpsd_report(0, "em_select: %s\n", strerror(errno));
exit(2);
}
} else {
if (select(FD_SETSIZE, &rfds, NULL, NULL, &tv) < 0) {
if (errno == EINTR)
continue;
gpsd_report(0, "select: %s\n", strerror(errno));
exit(2);
}
}
If necessary, I will post entire edited portion of gpsd.c
|