lkml.org 
[lkml]   [2005]   [Jul]   [12]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: Lack of Documentation about SA_RESTART...
    On Tue, 12 Jul 2005 10:38:11 +0200
    Paolo Ornati <ornati@fastwebnet.it> wrote:

    > The particular case you analized (blocking connect interrupted by a
    > SA_RESTART signal) is interesting... and since SUSV3 says
    > "but the connection request shall not be aborted, and the
    > connection shall be established asynchronously" (with select()
    > or poll()...)
    > both for EINPROGRESS and EINTR, I think it's quite stupit to
    > automatically restart it and then return EALREADY.
    >
    > The logically correct behaviur with blocking connect interrupted and
    > then restarted should be to continue the blocking wait... IHMO.

    it seems that Linux is doing the Right Thing... see the attached
    program...

    $ make
    gcc -O2 -Wall -o conntest connect_test.c


    FROM ANOTHER CONSOLE: this is needed to block connect()...
    # iptables -A OUTPUT -p tcp --dport 3500 -m state --state NEW -j DROP


    $ ./conntest WITHOUT_SA_RESTART
    connect(): errno = 4 # EINTR, as expected
    Cannot setup client!


    $ ./conntest # connect is restarted after SIGALRM, and then it blocks again


    FROM ANOTHER CONSOLE:
    # iptables -D OUTPUT -p tcp --dport 3500 -m state --state NEW -j DROP


    and then "conntest" (thanks to TCP protocol retries) will terminate.



    :-)

    --
    Paolo Ornati
    Linux 2.6.12.2 on x86_64
    #include <stdio.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <netinet/tcp.h>
    #include <signal.h>
    #include <unistd.h>

    void sighandler(int sig)
    {
    /* nothing :) */
    }

    int setup_alarm_handler(int flags)
    {
    struct sigaction sa = {
    .sa_handler = &sighandler,
    .sa_flags = flags
    };
    return sigaction(SIGALRM, &sa, NULL);
    }

    int setup_server(int port)
    {
    int sock;
    struct sockaddr_in sa = {
    .sin_family = AF_INET,
    .sin_port = htons(port),
    .sin_addr.s_addr = htonl(INADDR_ANY)
    };

    if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    goto error;
    if (bind(sock, (struct sockaddr*)&sa, sizeof(sa)) < 0)
    goto error_clean;
    if (listen(sock, 16) < 0)
    goto error_clean;
    return sock;

    error_clean:
    close(sock);
    error:
    return -1;
    }

    int setup_client(const char *server, int port)
    {
    int sock;
    struct sockaddr_in sa = {
    .sin_family = AF_INET,
    .sin_port = htons(port),
    .sin_addr.s_addr = inet_addr(server)
    };

    if ((sock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    goto error;
    if (connect(sock, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
    printf("connect(): errno = %d\n", errno);
    goto error_clean;
    }
    return sock;

    error_clean:
    close(sock);
    error:
    return -1;
    }

    int main(int argc, char *argv[])
    {
    int server, client;
    int flags = SA_RESTART;

    if (argc > 1)
    flags = 0;

    if (setup_alarm_handler(flags))
    return 1;

    server = setup_server(3500);
    if (server < 0) {
    printf("Cannot setup server!\n");
    return 1;
    }
    alarm(1);
    client = setup_client("127.0.0.1", 3500);
    if (client < 0) {
    printf("Cannot setup client!\n");
    return 1;
    }
    printf("Ok!\n");
    return 0;
    }
    [unhandled content-type:application/octet-stream]
    \
     
     \ /
      Last update: 2005-07-12 12:17    [W:0.027 / U:2.204 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site