Start the timeout after which we'll receive a SIGALRM. Round DURATION up to the next representable value. Treat out-of-range values as if they were maximal, as that's more useful in practice than reporting an error. '0' means don't timeout. */
| 112 | as that's more useful in practice than reporting an error. |
| 113 | '0' means don't timeout. */ |
| 114 | static void |
| 115 | settimeout (double duration, bool warn) |
| 116 | { |
| 117 | |
| 118 | #if HAVE_TIMER_SETTIME |
| 119 | /* timer_settime() provides potentially nanosecond resolution. */ |
| 120 | |
| 121 | struct timespec ts = dtotimespec (duration); |
| 122 | struct itimerspec its = {.it_interval = {0}, .it_value = ts}; |
| 123 | timer_t timerid; |
| 124 | if (timer_create (CLOCK_REALTIME, NULL, &timerid) == 0) |
| 125 | { |
| 126 | if (timer_settime (timerid, 0, &its, NULL) == 0) |
| 127 | return; |
| 128 | else |
| 129 | { |
| 130 | if (warn) |
| 131 | error (0, errno, _("warning: timer_settime")); |
| 132 | timer_delete (timerid); |
| 133 | } |
| 134 | } |
| 135 | else if (warn && errno != ENOSYS) |
| 136 | error (0, errno, _("warning: timer_create")); |
| 137 | |
| 138 | #elif HAVE_SETITIMER |
| 139 | /* setitimer() is more portable (to Darwin for example), |
| 140 | but only provides microsecond resolution. */ |
| 141 | |
| 142 | struct timeval tv; |
| 143 | struct timespec ts = dtotimespec (duration); |
| 144 | tv.tv_sec = ts.tv_sec; |
| 145 | tv.tv_usec = (ts.tv_nsec + 999) / 1000; |
| 146 | if (tv.tv_usec == 1000 * 1000) |
| 147 | { |
| 148 | if (tv.tv_sec != TYPE_MAXIMUM (time_t)) |
| 149 | { |
| 150 | tv.tv_sec++; |
| 151 | tv.tv_usec = 0; |
| 152 | } |
| 153 | else |
| 154 | tv.tv_usec--; |
| 155 | } |
| 156 | struct itimerval it = {.it_interval = {0}, .it_value = tv }; |
| 157 | if (setitimer (ITIMER_REAL, &it, NULL) == 0) |
| 158 | return; |
| 159 | else |
| 160 | { |
| 161 | if (warn && errno != ENOSYS) |
| 162 | error (0, errno, _("warning: setitimer")); |
| 163 | } |
| 164 | #endif |
| 165 | |
| 166 | /* fallback to single second resolution provided by alarm(). */ |
| 167 | |
| 168 | unsigned int timeint; |
| 169 | if (UINT_MAX <= duration) |
| 170 | timeint = UINT_MAX; |
| 171 | else |