Skip to content

Instantly share code, notes, and snippets.

@overhacked
Last active March 5, 2024 21:52
Show Gist options
  • Save overhacked/0b041af7994c06f9b6837876083deb72 to your computer and use it in GitHub Desktop.
Save overhacked/0b041af7994c06f9b6837876083deb72 to your computer and use it in GitHub Desktop.
Little C program to find the maximum value of select's timeout
#include <fcntl.h>
#include <limits.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/fcntl.h>
#include <sys/select.h>
/* min and max integer values. T is a signed or unsigned integer type. */
/* Returns 1 if T is signed, else 0. */
#define INTTYPE_SIGNED(T) ((T)-1 < (T)0)
/*
* Returns (T)(maximum value of a T).
*
* Pains are taken (perhaps unnecessarily) to avoid integer overflow
* with signed types.
*/
#define INTTYPE_MAX(T) \
(((T)1 << (CHAR_BIT*sizeof(T)-INTTYPE_SIGNED(T)-1)) - 1 + \
((T)1 << (CHAR_BIT*sizeof(T)-INTTYPE_SIGNED(T)-1)))
/*
* Returns (T)(minimum value of a T).
* Pains are taken (perhaps unnecessarily) to avoid integer overflow
* with signed types.
* assert: twos complement architecture
*/
#define INTTYPE_MIN(T) ((T)(-INTTYPE_MAX(T)-1))
/* Returns 1 if V has signed type, else 0. */
#define INT_VALUE_SIGNED(V) ((V)-(V)-1 < 0)
/*
* Returns maximum value for V's type.
*
* Pains are taken (perhaps unnecessarily) to avoid integer overflow
* with signed types.
*/
#define INT_VALUE_MAX(V) \
(((V)-(V)+1 << (CHAR_BIT*sizeof(V)-INT_VALUE_SIGNED(V)-1)) - 1 + \
((V)-(V)+1 << (CHAR_BIT*sizeof(V)-INT_VALUE_SIGNED(V)-1)))
/*
* Returns minimum value for V's type.
* Pains are taken (perhaps unnecessarily) to avoid integer overflow
* with signed types.
* assert: twos complement architecture
*/
#define INT_VALUE_MIN(V) (-INT_VALUE_MAX(V)-1)int: INT_MAX, unsigned int: UINT_MAX)
int
main(void)
{
int retval, devzero_fd;
fd_set rfds;
struct timeval tv;
__darwin_time_t search_lower, search_upper;
/* Read from /dev/zero, so there is always input */
devzero_fd = open("/dev/zero", O_RDONLY);
/* Decrement from the maximum value of tv.tv_sec to find the
* maximum value accepted by select(); start the lower bounds
* of the search at the max 32-bit integer, because it is a
* known-working value. */
// search_lower = INT_VALUE_MAX(tv.tv_sec) >> 31;
search_lower = 0;
search_upper = INT_VALUE_MAX(tv.tv_sec);
tv.tv_usec = 0;
while (search_lower <= search_upper) {
tv.tv_sec = search_lower + ((search_upper - search_lower) / 2);
printf("select(..., %ld)\n", tv.tv_sec);
FD_ZERO(&rfds);
FD_SET(devzero_fd, &rfds);
retval = select(devzero_fd + 1, &rfds, NULL, NULL, &tv);
if (retval > 0)
search_lower = tv.tv_sec + 1;
else if (retval < 0) {
search_upper = tv.tv_sec - 1;
}
}
if (retval == -1) {
tv.tv_sec -= 1;
if (!select(1, &rfds, NULL, NULL, &tv))
perror("select()");
}
printf("\nMaximum value for tv.tv_sec=%ld\n", tv.tv_sec);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment