Google Answers Logo
View Question
 
Q: c linux - select() function fd_set corruption ( No Answer,   0 Comments )
Question  
Subject: c linux - select() function fd_set corruption
Category: Computers > Programming
Asked by: dignome-ga
List Price: $9.50
Posted: 20 Mar 2005 12:34 PST
Expires: 21 Mar 2005 00:03 PST
Question ID: 497631
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
Answer  
There is no answer at this time.

Comments  
There are no comments at this time.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy