Subject: scheduler activations problem ?
To: None <current-users@netbsd.org>
From: Mihai CHELARU <kefren@netbastards.org>
List: current-users
Date: 10/20/2003 14:39:13
Hi,
I wrote a small program that is used mainly to link two irc servers (one
is using IPv4, the other one IPv6). I attached the source code below.
The problem is that after it gets one connection it starts spawning
threads like mad (at least that the opinion of `ps`, the test program
doesn't show that this is happening). After it reaches 4578 lwps it
stops. All these lwps are WCHANed as being in 'netcon'. Is my program
problem or is a SA problem ?
$ ps sx | grep test | grep -v grep | wc -l
4578
$ ps sx | grep test | grep -v grep | head
1000 6034 4085 0 4578 4578 28 0 344 464 sawait S- pa 0:36.02
./test
1000 6034 4085 0 4574 4578 2 0 344 464 select S- pa 0:36.02
./test
1000 6034 4085 0 4576 4578 2 0 344 464 select S- pa 0:36.02
./test
1000 6034 4085 0 4577 4578 2 0 344 464 netcon SW- pa 0:36.02
./test
1000 6034 4085 0 4575 4578 2 0 344 464 netcon SW- pa 0:36.02
./test
1000 6034 4085 0 4573 4578 2 0 344 464 select S- pa 0:36.02
./test
1000 6034 4085 0 4572 4578 2 0 344 464 netcon SW- pa 0:36.02
./test
1000 6034 4085 0 4571 4578 2 0 344 464 netcon SW- pa 0:36.02
./test
1000 6034 4085 0 4570 4578 2 0 344 464 netcon SW- pa 0:36.02
./test
1000 6034 4085 0 4569 4578 2 0 344 464 netcon SW- pa 0:36.02
./test
And here is the source code of test.c
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <unistd.h>
#include <stdlib.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#define INET_ADDR "80.86.105.74"
#define INET_PORT 6667
#define INET_ADDR2 "2001:470:1f00:477::2"
#define INET_PORT2 "7000"
#define MAXSOCKS 100
#define MAXNICKLEN 100
#define DEBUG
void *
sender(void *voidsoc)
{
fd_set fd, fd2;
int s, s1, r, *stmp;
char buf[1000];
struct timeval to = {1, 0};
stmp = (int *) (voidsoc);
s = stmp[0];
s1 = stmp[1];
#ifdef DEBUG
printf("Socket2: %d %d\n", s, s1);
#endif
FD_ZERO(&fd);
FD_SET(s, &fd);
for(;;) {
fd2 = fd;
if (!select(s + 1, &fd2, NULL, NULL, &to)) {
#ifdef DEBUG
printf("Timeout2\n");
#endif
if (stmp[2])
break;
continue;
}
r = recv(s, buf, 1000, MSG_PEEK);
if (r < 1)
break;
recv(s, buf, r, MSG_WAITALL);
#ifdef DEBUG
printf("Write2: %.*s\n", r, buf);
#endif
write(s1, buf, r);
}
#ifdef DEBUG
printf("Exiting thread2\n");
#endif
close(s);
stmp[3] = 1;
#ifdef DEBUG
printf("Thread2 gone\n");
#endif
pthread_exit(NULL);
}
void *
persocket(void *voidsoc)
{
int s, s1, r, psoc[4], *destroy_mutex_1, gaie;
char buf[1000];
fd_set fd;
pthread_t pt;
struct addrinfo hints, *res, *res0;
struct sockaddr_in6 sa;
struct timeval to = {1, 0};
s = accept((*(int *) (voidsoc)), NULL, NULL);
destroy_mutex_1 = &psoc[3];
destroy_mutex_1[0] = 0;
psoc[2] = 0;
/*
s1=socket (PF_INET6, SOCK_STREAM, 6);
sa.sin6_port=htons(INET_PORT2);
sa.sin6_family=AF_INET6;
sa.sin6_len=sizeof(sa);
if (!inet_aton (INET_ADDR2,&sa.sin6_addr)) perror ("inet_aton");
if (connect (s1,(struct sockaddr*)(&sa), sizeof(sa)) == -1)
{perror("connect");close(s);close(s1);return NULL;}
*/
hints.ai_family = PF_INET6;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = 0;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_addrlen = 0;
hints.ai_canonname = NULL;
hints.ai_addr = NULL;
hints.ai_next = NULL;
gaie = getaddrinfo(INET_ADDR2, INET_PORT2, &hints, &res0);
if (gaie) {
printf("getaddrinfo: %s\n", gai_strerror(gaie));
close(s);
return NULL;
}
for (res = res0; res0; res = res->ai_next) {
s1 = socket(res->ai_family, res->ai_socktype,
res->ai_protocol);
if (s1 < 0)
continue;
if (connect(s1, res->ai_addr, res->ai_addrlen) < 0) {
close(s1);
s1 = -1;
continue;
}
break;
}
freeaddrinfo(res0);
if (s1 < 0) {
perror("socket");
close(s);
return NULL;
}
psoc[0] = s1;
psoc[1] = s;
pthread_create(&pt, NULL, sender, (void *) (psoc));
pthread_detach(pt);
// pth_yield(NULL);
#ifdef DEBUG
printf("Socket1: %d %d\n", s, s1);
#endif
for (;;) {
FD_ZERO(&fd);
FD_SET(s, &fd);
to.tv_sec = 1;
to.tv_usec = 0;
if (!select(s + 1, &fd, NULL, NULL, &to)) {
#ifdef DEBUG
printf("Timeout1\n");
#endif
if (destroy_mutex_1[0])
break;
continue;
}
r = recv(s, buf, 1000, MSG_PEEK);
if (r < 1)
break;
recv(s, buf, r, MSG_WAITALL);
#ifdef DEBUG
printf("Write1: %.*s\n", r, buf);
#endif
write(s1, buf, r);
}
#ifdef DEBUG
printf("Exiting thread1\n");
#endif
psoc[2] = 1;
while (!psoc[3]) {
usleep(2000);
// pth_yield(NULL);
}
close(s);
#ifdef DEBUG
printf("Thread1 gone\n");
#endif
pthread_exit(NULL);
}
main()
{
int s;
struct sockaddr_in socka;
fd_set fs;
pthread_t pt;
#ifndef DEBUG
if (fork())
return 0;
#endif
signal(SIGPIPE, SIG_IGN);
s = socket(PF_INET, SOCK_STREAM, 6);
memset(&socka, 0, sizeof(socka));
socka.sin_len = sizeof(struct sockaddr_in);
socka.sin_port = htons(INET_PORT);
socka.sin_family = AF_INET;
inet_aton (INET_ADDR, &socka.sin_addr);
if (bind(s, (struct sockaddr *) (&socka), sizeof(socka)) == -1)
{
perror("bind");
close(s);
return 1;
}
if (listen(s, 500) == -1) {
perror("listen");
close(s);
return 2;
}
for(;;) {
FD_ZERO(&fs);
FD_SET(s, &fs);
select(s + 1, &fs, NULL, NULL, NULL);
if (pthread_create(&pt, NULL, persocket, (void *) (&s)))
perror("pthread_create");
if (pthread_detach(pt))
perror("pthread_detach");
// pth_yield(NULL);
}
close(s);
}
Thanks,
Mihai