/** * Reproduces http://code.google.com/p/go/issues/detail?id=6336 * * gcc -o bug6336 bug6336.c -lpthread */ #include #include #include #include #include #include #include #include #include #include #define LOOKUP_THREADS 1000 #define SOCKET_PATH "/tmp/test.sock" void* lookup_thread(void *_) { for (;;) { struct addrinfo *res; struct addrinfo hints; memset(&hints, 0, sizeof(hints)); if (0 == getaddrinfo("example.com", NULL, &hints, &res)) { freeaddrinfo(res); } } return NULL; } void lookup() { int i; for (i = 0; i < LOOKUP_THREADS; i++) { pthread_t t; pthread_attr_t ta; pthread_attr_init(&ta); pthread_attr_setstacksize(&ta, 100<<10); if (0 != pthread_create(&t, &ta, lookup_thread, (void*)(uintptr_t)i)) { perror("pthread_create lookup thread"); exit(1); } pthread_attr_destroy(&ta); } } void* server_thread(void *_) { struct sockaddr_un saddr; int s = socket(AF_UNIX, SOCK_STREAM, 0); memset(&saddr, 0, sizeof(saddr)); if (s == -1) { perror("server socket"); return NULL; } saddr.sun_family = AF_UNIX; strncpy(saddr.sun_path, SOCKET_PATH, sizeof(saddr.sun_path)-1); if (bind(s, (struct sockaddr *)&saddr, sizeof(struct sockaddr_un)) == -1) { perror("bind"); close(s); return NULL; } if (-1 == listen(s, 0)) { perror("listen"); close(s); return NULL; } for (;;) { struct sockaddr_un paddr; socklen_t paddrlen; int fd = accept(s, (struct sockaddr*) &paddr, &paddrlen); if (fd == -1) { perror("accept"); close(s); return NULL; } for (;;) { char c; int n = read(fd, &c, 1); fprintf(stderr, "BUG: has read char 0x%02hhx: %c\a\n", (unsigned int) c, c); if (n == 0) { break; } } close(fd); } return NULL; } void sock() { int s, i, m; struct sockaddr_un saddr; // open a client socket to SOCK_STREAM for (;;) { s = socket(AF_UNIX, SOCK_STREAM, 0); if (s == -1) { perror("socket"); sleep(1); continue; } memset(&saddr, 0, sizeof(saddr)); saddr.sun_family = AF_UNIX; strncpy(saddr.sun_path, SOCKET_PATH, sizeof(saddr.sun_path)-1); if (connect(s, (struct sockaddr *)&saddr, sizeof(struct sockaddr_un)) == -1) { perror("connect"); close(s); sleep(1); continue; } break; } // repeatedly fill the file descriptor space with dups of the socket, and close the dups int fds[65536]; for (;;) { for (i = 0, m = 0; i < sizeof(fds)/sizeof(*fds); i++) { int fd = dup(s); if (fd == -1) { if (errno == EMFILE) { break; } else { perror("dup"); } } fds[i] = fd; m = i; } for (i = 0; i <= m; i++) { close(fds[i]); } continue; } } int main() { // Listen on SOCKET_PATH; if we receive something on this socket, we have // successfuly reproduced the bug unlink(SOCKET_PATH); pthread_t t; if (0 != pthread_create(&t, NULL, server_thread, NULL)) { perror("pthread_create server thread"); return 1; } // Do many getaddrinfo() in parallel lookup(); // Connect to SOCKET_PATH and dup()&close() the fd repeatedly sock(); return 0; }