// // bug.cxx. Compile with "gcc -o bug bug.c -lpthread" // #include #include #include #include #include #include #include #include #include #include #include #define SERVER_PORT 9999 pthread_t tobject; static void *server_thread(void* arg) { int s, conn; struct sockaddr_in sa; struct pollfd pfd; unsigned flags; if ( (s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror("socket"); exit(-1); } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(SERVER_PORT); if ( bind(s, (struct sockaddr*)&sa, sizeof(sa)) ) { perror("bind"); close(s); exit(-1); } if ( listen(s, 1) ) { perror("listen"); close(s); exit(-1); } conn = accept(s,NULL,NULL); if ( conn < 0 ) { perror("accept"); close(s); exit(-1); } flags = fcntl(conn, F_GETFL); if ( fcntl(conn, F_SETFL, flags | O_NONBLOCK) ) { perror("fcntl"); close(conn); close(s); exit(-1); } pfd.fd = conn; pfd.events = POLLIN; switch ( poll(&pfd, 1, 10000) ) { case 0: printf("TIMEOUT\n"); break; case 1: if ( pfd.revents & POLLIN ) printf("POLLIN "); if ( pfd.revents & POLLPRI ) printf("POLLPRI "); if ( pfd.revents & POLLERR ) printf("POLLERR "); if ( pfd.revents & POLLHUP ) printf("POLLHUP "); if ( pfd.revents & POLLNVAL ) printf("POLLNVAL "); printf("\n"); break; default: perror("poll"); close(conn); close(s); exit(-1); break; } close(conn); close(s); } int conn_test(const char *tname) { int conn; struct sockaddr_in sa; printf("%s: ", tname); if ( errno = pthread_create(&tobject, 0, server_thread, 0) ) { perror("pthread_create"); return -1; } sleep(1); if ( (conn = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) { perror("socket"); return -1; } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = inet_addr("127.0.0.1"); sa.sin_port = htons(SERVER_PORT); if ( connect(conn,(struct sockaddr *)&sa, sizeof(sa)) < 0 ) { perror("connect"); return -1; } return conn; } int main() { int conn; if ( (conn = conn_test("close")) < 0 ) return -1; close(conn); pthread_join(tobject, 0); if ( (conn = conn_test("shutdown")) < 0 ) return -1; shutdown(conn,2); pthread_join(tobject, 0); return 0; }