Oracle Bug 14961740 - SUNBT4136406 dtgreet runs wild and error messages
    fill /var/dt/Xerrors
Oracle Bug 15072668 - SUNBT4482749 Xt spins forever when select() returns EBADF

Changed handling of select() error to not retry indefinitely.

Description of 14961740:
When select() returns EINVAL, investigate whether this condition is caused by an
invalid timeout value, or whether one of the fds in the fd_set is invalid. If
the problem is caused by the timeout value, then the problem can be cured by
adjusting these. If the problem arises because of the fd_set, then Xt can do
little better than to terminate the application, since it has no direct way of
curing the condition.

Description of 15072668:
_XtWaitForSomething did not explicity check for EBADF.  This caused the function
to continuously call select for the bad file descriptor leading to an infinite
loop.

Added in an error handler for this particular error.

In the event of an EBADF, the Xt removes all Input Procedures that monitor the
offending file descriptor.  This prevents it from repeating checks which are
going to fail.

Additionally, an XtWarning is issued to the user.  An XtError is too much as
it will dump the user out of the program.

Finally, the error handler returns -1 from _XtWaitForSomething().


Need to evaluate for submission upstream.

--- a/configure.ac	2022-11-07 19:20:45.189568737 -0800
+++ b/configure.ac	2022-11-07 19:21:07.279113999 -0800
@@ -80,6 +80,7 @@
 
 # Map function checks to old Imake #defines
 case $host_os in
+	solaris*) ;; # our changes to NextEvent.c break if poll() is used
 	# darwin through Snow Leopard has poll() but can't be used to poll character devices.
 	darwin@<:@789@:>@*|darwin10*) ;;
 	darwin*)
--- a/src/NextEvent.c	2022-11-07 19:21:23.489203221 -0800
+++ b/src/NextEvent.c	2022-11-07 19:29:41.331516786 -0800
@@ -367,6 +367,53 @@
     }
 }
 
+static void CheckAndTrimTimes(XtAppContext app, wait_times_ptr_t wt)
+{
+   struct timeval tv;
+   String         pptrs[8];
+   Cardinal       nbr_parms;
+
+   pptrs[0] = (String)zero_time.tv_sec;
+   pptrs[1] = (String)zero_time.tv_usec;
+   pptrs[2] = (String)wt->wait_time.tv_sec;
+   pptrs[3] = (String)wt->wait_time.tv_usec;
+   pptrs[4] = (String)wt->max_wait_time.tv_sec;
+   pptrs[5] = (String)wt->max_wait_time.tv_usec;
+   pptrs[6] = (String)wt->cur_time.tv_sec;
+   pptrs[7] = (String)wt->cur_time.tv_usec;
+   nbr_parms = 8;
+   XtAppErrorMsg(app, "communicationError", "select",
+                 XtCXtToolkitError, "Resetting timer values: zero_time=%lu:%lu, "
+                 "wait_time=%lu:%lu, max_wait_time=%lu:%lu, cur_time=%lu:%lu",
+                 pptrs, &nbr_parms);
+
+   memset(&zero_time, 0, sizeof(zero_time)); /* Ensure the integrity of       */
+                                             /* zero_time.                    */
+   if (wt->max_wait_time.tv_sec > 99999999)  /* Bring max_wait_time back into */
+    {                                        /* acceptable range if nec.      */
+      wt->max_wait_time.tv_sec &= 0xFFFFF;
+      wt->max_wait_time.tv_usec = 0;         /* (Fractions of a sec are in-   */
+                                             /*  significant at this level.)  */
+    }
+   if (app->timerQueue != NULL)              /* Do the same for the head of   */
+    {                                        /* the timer queue if necessary. */
+      TIMEDELTA(tv, app->timerQueue->te_timer_value, wt->cur_time);
+      if (tv.tv_sec > 99999999)
+       {
+         pptrs[0] = (String)app->timerQueue->te_timer_value.tv_sec;
+         pptrs[1] = (String)app->timerQueue->te_timer_value.tv_usec;
+         nbr_parms = 2;
+         XtAppErrorMsg(app, "selectError", "timerQueue",
+                       XtCXtToolkitError, "timerQueue value %lu:%lu is invalid",
+                       pptrs, &nbr_parms);
+         tv.tv_sec &= 0xFFFFF;
+         tv.tv_usec = 0;
+         ADD_TIME(app->timerQueue->te_timer_value, wt->cur_time, tv);
+       }
+    }
+}
+
+
 static int
 IoWait(wait_times_ptr_t wt, wait_fds_ptr_t wf)
 {
@@ -717,17 +799,32 @@
                         nfds = 0;
                 }
             }
-            else {
-                char Errno[12];
-                String param = Errno;
-                Cardinal param_count = 1;
+            else if (errno == EINVAL) {
+                struct timeval  tv={0};
 
-                sprintf(Errno, "%d", errno);
-                XtAppWarningMsg(app, "communicationError", "select",
-                                XtCXtToolkitError,
-                                "Select failed; error code %s", &param,
-                                &param_count);
-                continue;
+                nfds = Select(wf.nfds, &wf.rmask, &wf.wmask, &wf.emask, &tv);
+                                                /* Do a non-blocking select to  */
+                                                /* eliminate any timeout errors.*/
+                if (nfds == -1) {               /* Now try to sort out the good */
+                    if (errno == EINVAL) {      /* and the bad from the ugly.   */
+                        char    Errno[12];      /* (This is ugly).              */
+                        String  param = Errno;
+                        Cardinal param_count = 1;
+
+                        sprintf(Errno, "%d", errno);
+                        XtAppErrorMsg(app, "communicationError", "select",
+                                      XtCXtToolkitError, "Select failed; error code %s",
+                                      &param, &param_count);
+                        XtAppError(app, "EINVAL error in select() call");
+                    } else {                    /* If the new error is not about */
+                                                /* an invalid select() parameter,*/
+                        continue;               /* then simply try again.        */
+                    }
+                } else {                        /* (Else the error appears to be */
+                                                /* in the timeout parameter.)    */
+                    CheckAndTrimTimes(app, &wt);
+                    continue;
+                }
             }
         }                       /* timed out or input available */
         break;
--- a/src/NextEvent.c	2024-08-23 17:16:20.202048925 -0700
+++ b/src/NextEvent.c	2024-08-23 17:19:37.616146755 -0700
@@ -696,13 +696,48 @@
             /*
              *  interrupt occurred recalculate time value and wait again.
              */
-            if (errno == EINTR || errno == EAGAIN) {
-                if (errno == EAGAIN) {
+            if (errno == EAGAIN) {
                     errno = 0;  /* errno is not self resetting */
                     continue;
-                }
-                errno = 0;      /* errno is not self resetting */
+            } else if (errno == EBADF) {
+                /* Bug 4482749 - If we have a bad FD stop monitoring it */
+                int i;
+                struct timeval tv={0};
+                for (i = 0; i < wf.nfds; i++) {
+                    if (FD_ISSET(i, &wf.rmask) || FD_ISSET(i, &wf.wmask) ||
+                          FD_ISSET(i, &wf.emask)) {
+                        if (select(i + 1, &wf.rmask, &wf.wmask, &wf.emask, &tv)
+                              == -1) {
+                            char     bad_fd[55];
+                            String   param = bad_fd;
+                            Cardinal param_count = 1;
+                            /*
+                             * Get rid of any input procedures on the bad FD
+                             * and regenerate the list of FDs we listen to.
+                             */
+                            while (app->input_list[i] != NULL) {
+                              XtRemoveInput((XtInputId)app->input_list[i]);
+                            }
+                            InitFds (app, ignoreEvents, ignoreInputs, &wf);
 
+                            sprintf(bad_fd, "%d", errno);
+                            XtAppWarningMsg(app, "communicationError", "select",
+                                            XtCXtToolkitError,
+                                            "Select failed; error code %s",
+                                            &param, &param_count);
+
+                            sprintf(bad_fd, "EBADF error in select() call for file descriptor %d", i);
+                            XtAppWarning(app, param);
+
+                          }
+                      }
+                  }
+
+                return -1;
+
+                } else if (errno == EINTR) {
+                           errno = 0;      /* errno is not self reseting */
+
                 /* was it interrupted by a signal that we care about? */
                 if (!ignoreSignals && app->signalQueue != NULL) {
                     SignalEventRec *se_ptr = app->signalQueue;
@@ -710,7 +745,7 @@
                     while (se_ptr != NULL) {
                         if (se_ptr->se_notice) {
                             if (block && howlong != NULL)
-                                AdjustHowLong(howlong, &wt.start_time);
+                                AdjustHowLong (howlong, &wt.start_time);
 #ifdef USE_POLL
                             XtStackFree((XtPointer) wf.fdlist, fdlist);
 #endif
