1 /* $OpenBSD: setsockopt3a.c,v 1.6 2012/02/22 20:33:51 fgsch Exp $ */ 2 /* 3 * Federico G. Schwindt <fgsch@openbsd.org>, 2009. Public Domain. 4 */ 5 6 #include <sys/types.h> 7 #include <sys/time.h> 8 #include <sys/socket.h> 9 #include <netinet/in.h> 10 #include <err.h> 11 #include <fcntl.h> 12 #include <netdb.h> 13 #include <stdlib.h> 14 #include <string.h> 15 #include <unistd.h> 16 #include "test.h" 17 18 /* resolution of the monotonic clock */ 19 struct timespec mono_res; 20 21 static void 22 alarm_handler(int sig) 23 { 24 _exit(NOTOK); 25 } 26 27 void 28 check_timeout(int s, int sec, const struct timespec *to) 29 { 30 struct timespec t1, t2, e; 31 char buf[BUFSIZ]; 32 33 ASSERT(signal(SIGALRM, alarm_handler) != SIG_ERR); 34 CHECKe(alarm(sec)); 35 CHECKe(clock_gettime(CLOCK_MONOTONIC, &t1)); 36 ASSERT(read(s, &buf, sizeof(buf)) == -1); 37 CHECKe(clock_gettime(CLOCK_MONOTONIC, &t2)); 38 ASSERT(errno == EAGAIN); 39 timespecsub(&t2, &t1, &e); 40 41 /* 42 * verify that the difference between the duration and the 43 * timeout is less than the resolution of the clock 44 */ 45 if (timespeccmp(&e, to, <)) 46 timespecsub(to, &e, &t1); 47 else 48 timespecsub(&e, to, &t1); 49 ASSERT(timespeccmp(&t1, &mono_res, <=)); 50 } 51 52 static void * 53 sock_accept(void *arg) 54 { 55 struct sockaddr_in sin; 56 struct timeval to; 57 struct timespec ts; 58 int s, s2, s3; 59 60 CHECKe(clock_getres(CLOCK_MONOTONIC, &mono_res)); 61 CHECKe(s = strtol(arg, NULL, 10)); 62 bzero(&sin, sizeof(sin)); 63 sin.sin_family = AF_INET; 64 sin.sin_len = sizeof(sin); 65 sin.sin_port = htons(6545); 66 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 67 CHECKe(connect(s, (struct sockaddr *)&sin, sizeof(sin))); 68 to.tv_sec = 2; 69 to.tv_usec = 0.5 * 1e6; 70 TIMEVAL_TO_TIMESPEC(&to, &ts); 71 check_timeout(s, 3, &ts); 72 CHECKe(s2 = dup(s)); 73 CHECKe(s3 = fcntl(s, F_DUPFD, s)); 74 check_timeout(s2, 3, &ts); 75 check_timeout(s3, 3, &ts); 76 return (NULL); 77 } 78 79 int 80 main(int argc, char **argv) 81 { 82 pthread_t accept_thread; 83 84 if (argc != 2) 85 exit(NOTOK); 86 CHECKr(pthread_create(&accept_thread, NULL, sock_accept, argv[1])); 87 CHECKr(pthread_join(accept_thread, NULL)); 88 SUCCEED; 89 } 90