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.157 / U:0.272 seconds]
©2003-2014 Jasper Spaans. Advertise on this site