On Tue, 12 Jul 2005 10:38:11 +0200 Paolo Ornati <[email protected]> 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; }
Attachment:
Makefile
Description: Binary data
- References:
- Lack of Documentation about SA_RESTART...
- From: Paolo Ornati <[email protected]>
- Re: Lack of Documentation about SA_RESTART...
- From: "Theodore Ts'o" <[email protected]>
- Re: Lack of Documentation about SA_RESTART...
- From: Paolo Ornati <[email protected]>
- Lack of Documentation about SA_RESTART...
- Prev by Date: Re: [PATCH] [3/48] Suspend2 2.1.9.8 for 2.6.12: 301-proc-acpi-sleep-activate-hook.patch
- Next by Date: Re: Problems with more than 8 AMD Opteron Cores per System
- Previous by thread: Re: Lack of Documentation about SA_RESTART...
- Next by thread: Re: Lack of Documentation about SA_RESTART...
- Index(es):