lkml.org 
[lkml]   [2003]   [Sep]   [1]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    From
    SubjectBug in linux-2.6.0-test4 ?
    Date
    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 <stdio.h>
    # include <sys/socket.h>
    # include <netinet/tcp.h>
    # include <arpa/inet.h>
    # include <netdb.h>
    # include <unistd.h>
    # include <string.h>

    /*
    * 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 ;
    }
    /********************************************************************/
    /*
    * 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 <stdio.h>
    # include <sys/socket.h>
    # include <netinet/tcp.h>
    # include <arpa/inet.h>
    # include <netdb.h>
    # include <unistd.h>
    # include <string.h>

    /*
    * 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 ;
    }
    /********************************************************************/
    \
     
     \ /
      Last update: 2005-03-22 13:48    [W:0.034 / U:0.588 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site