[comp.windows.x] the elusive select

jordan@morgan.COM (Jordan Hayes) (03/12/90)

Sun4/110, X11R4 patches 1-5 installed, SunOS 4.0.3 ... but i've seen it
since R3 about a year ago.

Symptom: Xt clients enter spin loop warning select() failed: errno 22

-----

I got some mail about this from someone who tipped me off.  Somehow
(don't ask me!) ntpd (the network time protocol daemon) is screwing up
the system time on Sparcs so that the return from gettimeofday()
contains an unusable time.  The macros ADD_TIME and TIME_DELTA in
mit/lib/Xt/NextEvent.c do a good job of sanity checking the two time
values, but don't go far enough in the face of stupid input.  This is
not their fault.  However, here's a more bullet-proof version of these
macros, ones that will avoid similar problems in the future.

After adjusting for the border conditions, if there are still negative
numbers involved in tv_sec or tv_usec (refused as invalid input for the
timeout argument to select()) they are quashed.

*** NextEvent.c	Mon Mar 12 10:44:29 1990
--- NextEvent.c.old	Mon Mar 12 10:37:19 1990
***************
*** 53,71 ****
   * Private routines
   */
  #define ADD_TIME(dest, src1, src2) { \
! 	if(((dest).tv_usec = (src1).tv_usec + (src2).tv_usec) >= 1000000) {\
! 	      (dest).tv_usec -= 1000000;\
! 	      (dest).tv_sec = (src1).tv_sec + (src2).tv_sec + 1 ; \
! 	} else { (dest).tv_sec = (src1).tv_sec + (src2).tv_sec ; \
! 	   if(((dest).tv_sec >= 1) && (((dest).tv_usec <0))) { \
! 	    (dest).tv_sec --;(dest).tv_usec += 1000000; } } }
  
- 
  #define TIMEDELTA(dest, src1, src2) { \
! 	if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) {\
! 	      (dest).tv_usec += 1000000;\
! 	      (dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1;\
! 	} else 	(dest).tv_sec = (src1).tv_sec - (src2).tv_sec;  }
  
  #define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
  	|| (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec)))
--- 53,71 ----
   * Private routines
   */
  #define ADD_TIME(dest, src1, src2) { \
! 	(dest).tv_sec = (src1).tv_sec + (src2).tv_sec; \
! 	(dest).tv_usec = (src1).tv_usec + (src2).tv_usec; \
! 	while ((dest).tv_usec >= 1000000) { \
! 		(dest).tv_usec -= 1000000; (dest).tv_sec++; } \
! 	if ((dest).tv_sec < 0) (dest)tv_sec = 0; \
! 	if ((dest).tv_usec < 0) (dest)tv_usec = 0; }
  
  #define TIMEDELTA(dest, src1, src2) { \
! 	(dest).tv_sec = (src1).tv_sec - (src2).tv_sec; \
! 	(dest).tv_usec = (src1).tv_usec - (src2).tv_usec; \
! 	while ((dest).tv_usec < 0) { \
! 		(dest).tv_usec += 1000000; (dest).tv_sec--; } \
! 	if ((dest).tv_sec < 0) (dest)tv_sec = 0; }
  
  #define IS_AFTER(t1, t2) (((t2).tv_sec > (t1).tv_sec) \
  	|| (((t2).tv_sec == (t1).tv_sec)&& ((t2).tv_usec > (t1).tv_usec)))

-----

/jordan