1/*++
2/* NAME
3/*	select_bug 1
4/* SUMMARY
5/*	select test program
6/* SYNOPSIS
7/*	select_bug
8/* DESCRIPTION
9/*	select_bug forks child processes that perform select()
10/*	on a shared socket, and sees if a wakeup affects other
11/*	processes selecting on a different socket or stdin.
12/* DIAGNOSTICS
13/*	Problems are reported to the standard error stream.
14/* LICENSE
15/* .ad
16/* .fi
17/*	The Secure Mailer license must be distributed with this software.
18/* AUTHOR(S)
19/*	Wietse Venema
20/*	IBM T.J. Watson Research
21/*	P.O. Box 704
22/*	Yorktown Heights, NY 10598, USA
23/*--*/
24
25/* System library. */
26
27#include <sys_defs.h>
28#include <sys/time.h>
29#include <sys/socket.h>
30#include <sys/wait.h>
31#include <unistd.h>
32#include <stdlib.h>
33#include <string.h>			/* bzero() prototype for 44BSD */
34
35/* Utility library. */
36
37#include <msg.h>
38#include <vstream.h>
39#include <msg_vstream.h>
40
41static pid_t fork_and_read_select(const char *what, int delay, int fd)
42{
43    struct timeval tv;
44    pid_t   pid;
45    fd_set  readfds;
46
47    switch (pid = fork()) {
48    case -1:
49	msg_fatal("fork: %m");
50    case 0:
51	tv.tv_sec = delay;
52	tv.tv_usec = 0;
53	FD_ZERO(&readfds);
54	FD_SET(fd, &readfds);
55	switch (select(fd + 1, &readfds, (fd_set *) 0, &readfds, &tv)) {
56	case -1:
57	    msg_fatal("select: %m");
58	case 0:
59	    msg_info("%s select timed out", what);
60	    exit(0);
61	default:
62	    msg_info("%s select wakeup", what);
63	    exit(0);
64	}
65    default:
66	return (pid);
67    }
68}
69
70int     main(int argc, char **argv)
71{
72    int     pair1[2];
73    int     pair2[2];
74
75    msg_vstream_init(argv[0], VSTREAM_ERR);
76
77#define DELAY 1
78
79    if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair1) < 0)
80	msg_fatal("socketpair: %m");
81    if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair2) < 0)
82	msg_fatal("socketpair: %m");
83
84    vstream_printf("Doing multiple select on socket1, then write to it...\n");
85    vstream_fflush(VSTREAM_OUT);
86    fork_and_read_select("socket1", DELAY, pair1[0]);	/* one */
87    fork_and_read_select("socket1", DELAY, pair1[0]);	/* two */
88    fork_and_read_select("socket2", DELAY, pair2[0]);
89    fork_and_read_select("stdin", DELAY, 0);
90    if (write(pair1[1], "", 1) != 1)
91	msg_fatal("write: %m");
92    while (wait((int *) 0) >= 0)
93	 /* void */ ;
94    return (0);
95}
96