#include #include #include #include #include #include "test.h" #include "tests.h" typedef struct priv PRIV; struct priv { int nbio; int lfd; int cfd; } ; static void set_nbio(int fd) { fcntl(fd,F_SETFL,fcntl(fd,F_GETFL,0)|O_NONBLOCK); } static void run_empty_eof_run_l(void *pv) { PRIV *p; pid_t mypid; int fd; int fd2; char c; LLI lts; LLI cts; LLI d; p = pv; mypid = getpid(); printf("empty-eof: listener is %d\n",(int)mypid); printf("empty-eof: listener establishing connection\n"); sleep(1); SET_PIDCONN(fd,PIDCONN_LISTEN,0,0); mustwrite(p->lfd,&mypid,sizeof(pid_t)); SET_PIDCONN(fd2,PIDCONN_ACCEPT,fd,0); sleep(1); mustwrite(p->lfd,"",1); mustread(p->lfd,&c,1); sleep(1); close(fd2); lts = tstamp(); mustread(p->lfd,&cts,sizeof(LLI)); sleep(1); d = lts - cts; if ((d < -250000) || (d > 250000)) { printf("empty-eof: time delta %lld too large\n",d); test_fail(); } printf("empty-eof: time delta %lld\n",d); printf("empty-eof: listener done\n"); sleep(1); } static void run_empty_eof_run_c(void *pv) { PRIV *p; pid_t lpid; int fd; char c; struct pollfd pfd; int i; LLI ts; p = pv; printf("empty-eof: connecter is %d\n",(int)getpid()); printf("empty-eof: connecter establishing connection\n"); sleep(1); mustread(p->cfd,&lpid,sizeof(pid_t)); SET_PIDCONN(fd,PIDCONN_CONNECT,0,lpid); if (p->nbio) set_nbio(fd); sleep(1); mustread(p->cfd,&c,1); mustwrite(p->cfd,"",1); pfd.fd = fd; pfd.events = POLLIN | POLLRDNORM; while (1) { i = poll(&pfd,1,5000); if (i < 0) { i = errno; printf("empty-eof: poll: %s\n",strerror(i)); if (i == EINTR) continue; test_fail(); } if (i == 0) { printf("empty-eof: poll timed out\n"); test_fail(); } break; } i = read(fd,&c,1); if (i < 0) { printf("empty-eof: read: %s\n",strerror(errno)); test_fail(); } if (i > 0) { printf("empty-eof: read worked, expected EOF\n"); test_fail(); } ts = tstamp(); mustwrite(p->cfd,&ts,sizeof(LLI)); sleep(1); printf("empty-eof: connecter done\n"); sleep(1); } static void do_empty_eof(int nb) { PRIV p; KID *kl; KID *kc; printf("empty-eof: >>>>>>>> nb = %d\n",nb); local_socketpair(&p.lfd,&p.cfd); p.nbio = nb; kl = fork_kid(&run_empty_eof_run_l,&p); kc = fork_kid(&run_empty_eof_run_c,&p); close(p.lfd); close(p.cfd); reap_kid(kl); reap_kid(kc); } static void run_empty_eof(void) { do_empty_eof(0); do_empty_eof(1); printf("empty-eof: done\n"); } const TEST test_empty_eof = { &run_empty_eof };