Hi all I have an annoying problem with a network server (TCP sockets) On some stress situation, LowMemory goes close to 0, and the whole machine freezes. When the sockets receive a lot of data, and the server is busy, the TCP stack just can use too many buffers (in LowMem). TCP stack uses "size-4096" buffers to store the datas, even if only one byte is coming from the network. I tried to change /proc/sys/net/ipv4/tcp_mem, without results. # echo "1000 10000 15000" >/proc/sys/net/ipv4/tcp_mem You can reproduce the problem with the test program attached. # gcc -o crash crash.c # ulimit -n 20000 # ./crash listen 8888 & # ./crash call 127.0.0.1:8888 & grep "size-4096 " /proc/slabinfo size-4096 40015 40015 4096 1 1 : tunables 24 12 0 : slabdata 40015 40015 0 (thats is 160 Mo, far more than the limit given in /proc/sys/net/ipv4/tcp_mem) grep TCP /proc/net/sockstat TCP: inuse 39996 orphan 0 tw 0 alloc 39997 mem 79986 What is the unit of 'mem' field ? Unless it is 2Ko, the numbers are wrong. How may I ask the kernel NOT to use more than 'X Mo' to store TCP messages ? Thanks Eric Dumazet /* * Program to freeze a linux box, by using all the LOWMEM * A bug on the tcp stack may be the reason * Use at your own risk !! */ /* Principles : A listener accepts incoming tcp sockets, write 40 bytes, and does nothing with them (no reading) A writer establish TCP sockets, sends some data (40 bytes), no more reading/writing */ #include # include # include # include # include # include # include /* * Usage : * crash listen port * crash call IP:port */ void usage(int code) { fprintf(stderr, "Usages :\n") ; fprintf(stderr, " crash listen port\n") ; fprintf(stderr, " crash call IP:port\n") ; exit(code) ; } const char some_data[40] = "some data.... just some data" ; void do_listener(const char *string) { int port = atoi(string) ; struct sockaddr_in host, from ; int fdlisten ; unsigned int total ; socklen_t fromlen ; memset(&host,0, sizeof(host)); host.sin_family = AF_INET; host.sin_port = htons(port); fdlisten = socket(AF_INET, SOCK_STREAM, 0) ; if (bind(fdlisten, (struct sockaddr *)&host, sizeof(host)) == -1) { perror("bind") ; return ; } listen(fdlisten, 10) ; for (total=0;;total++) { int nfd ; fromlen = sizeof(from) ; nfd = accept(fdlisten, (struct sockaddr *)&from, &fromlen) ; if (nfd == -1) break ; write(nfd, some_data, sizeof(some_data)) ; } printf("total=%u\n", total) ; pause() ; } void do_caller(const char *string) { union { int i ; char c[4] ; } u ; struct sockaddr_in dest; int a1, a2, a3, a4, port ; unsigned int total ; sscanf(string, "%d.%d.%d.%d:%d", &a1, &a2, &a3, &a4, &port) ; u.c[0] = a1 ; u.c[1] = a2 ; u.c[2] = a3 ; u.c[3] = a4 ; for (total=0;;total++) { int fd ; memset(&dest, 0, sizeof(dest)) ; dest.sin_family = AF_INET ; dest.sin_port = htons(port) ; dest.sin_addr.s_addr = u.i ; fd = socket(AF_INET, SOCK_STREAM, 0) ; if (fd == -1) break ; if (connect(fd, (struct sockaddr *)&dest, sizeof(dest)) == -1) { perror("connect") ; break ; } write(fd, some_data, sizeof(some_data)) ; } printf("total=%u\n", total) ; pause() ; } int main(int argc, char *argv[]) { int listener ; int caller ; if (argc != 3) { usage(1); } listener = !strcmp(argv[1], "listen") ; caller = !strcmp(argv[1], "call") ; if (listener) { do_listener(argv[2]) ; } else if (caller) { do_caller(argv[2]) ; } else usage(2) ; return 0 ; } /********************************************************************/