Discussion:
creating a socket connection timeout in "C" linux
(too old to reply)
d-fan
2008-06-06 06:43:46 UTC
Permalink
How can I open a socket connection with a timeout? Currently when I
make a call like "var = socket(" if the internet is down or there is
a problem reaching the destination computer, my programs behaves like
it is freezing. It here a way to control this behavior via a timeout
or any other method so that if the destination cannot then my program
will not hang?
t***@googlemail.com
2008-06-06 08:11:45 UTC
Permalink
Post by d-fan
How can I open a socket connection with a timeout? Currently when I
make a call like "var = socket(" if the internet is down or there is
a problem reaching the destination computer, my programs behaves like
it is freezing. It here a way to control this behavior via a timeout
or any other method so that if the destination cannot then my program
will not hang?
The socket() call should never hang. If it does it means either the OS
is very busy or theres something wierd happening.

I assume you're writing a client and mean connect() hangs? In which
case you can either spawn a seperate thread or process to run the
connect in , or you can set the socket to non blocking which means
connect() will return immediately and then you wait in a select() for
the write descriptor to be set. This can be quite tricky to code so
its probably best you buy a book such as Unix Network Programming or
similar. However some example code would be:

iif ((sock = socket(AF_INET,SOCK_STREAM,0)) == -1)
{
do something
}
flags = fcntl(sock,F_GETFL,0);
fcntl(sock,F_SETFL, flags | O_NONBLOCK)

if (!connect(sock,....))
{
got immediate connect
}

if (errno != EINPROGRESS)
{
perror("connect"); exit(1);
}
FD_ZERO(&wset);
FD_SET(sock,&wset);
timeout.tv_sec=1;
timeout.tv_usec=0;

/* Wait for write bit to be set */
switch (select(FD_SETSIZE,0,&wset,0,&timeout))
{
}

Obviously you'll need to fill in lots of code above but thats the
general idea of how to write a single threaded non blocking connect.

B2003
Rainer Weikusat
2008-06-06 09:30:10 UTC
Permalink
Post by d-fan
How can I open a socket connection with a timeout? Currently when I
make a call like "var = socket(" if the internet is down or there is
a problem reaching the destination computer, my programs behaves like
it is freezing. It here a way to control this behavior via a timeout
This is already done by the kernel. According to RFC1122 4.2.3.5 a SYN
(TCP connection initiation request) must be retransmitted for at least
three minutes before establishing the connection is considered to have
failed. Assuming that you (like your countless predecessors) really
believe that the cross sum of the bust size of your girl friend is a
number you just happen to like a lot more, the easy, unreliable way
to enforce a shorter timeout is alarm(3).
Alex Fraser
2008-06-06 17:26:36 UTC
Permalink
Post by Rainer Weikusat
Post by d-fan
How can I open a socket connection with a timeout? Currently when I
make a call like "var = socket(" if the internet is down or there is
a problem reaching the destination computer, my programs behaves like
it is freezing. It here a way to control this behavior via a timeout
This is already done by the kernel. According to RFC1122 4.2.3.5 a SYN
(TCP connection initiation request) must be retransmitted for at least
three minutes before establishing the connection is considered to have
failed. Assuming that you (like your countless predecessors) really
believe that the cross sum of the bust size of your girl friend is a
number you just happen to like a lot more, the easy, unreliable way
to enforce a shorter timeout is alarm(3).
What makes alarm() unreliable?

Alex
Rainer Weikusat
2008-06-06 18:30:48 UTC
Permalink
Post by Alex Fraser
Post by d-fan
How can I open a socket connection with a timeout?
[...]
Post by Alex Fraser
the easy, unreliable way to enforce a shorter timeout is alarm(3).
What makes alarm() unreliable?
I was being too imprecise. The 'easy, unreliable timeout' is setting
up a no-op handler for SIGALRM and relying on the alarm signal to
interrupt the connect. The problem is that 'setting up an alarm' and
'starting to connect' are two operations instead of one atomic
operation and their can be a near arbitrary delay between them because
other processes could be scheduled. This means there is a chance that
the SIGALRM may actually be posted to the process before the connect
ever blocks.
Alex Fraser
2008-06-06 18:59:04 UTC
Permalink
Post by Rainer Weikusat
Post by Alex Fraser
Post by d-fan
How can I open a socket connection with a timeout?
[...]
Post by Alex Fraser
the easy, unreliable way to enforce a shorter timeout is alarm(3).
What makes alarm() unreliable?
I was being too imprecise. The 'easy, unreliable timeout' is setting
up a no-op handler for SIGALRM and relying on the alarm signal to
interrupt the connect. The problem is that 'setting up an alarm' and
'starting to connect' are two operations instead of one atomic
operation and their can be a near arbitrary delay between them because
other processes could be scheduled. This means there is a chance that
the SIGALRM may actually be posted to the process before the connect
ever blocks.
But you'd have the same "near arbitrary delay" even if there was an
atomic "connect() with timeout" call, between timeout/connect success
and the thread being scheduled again. So are you any worse off?

Alex
Rainer Weikusat
2008-06-08 17:25:19 UTC
Permalink
Post by Alex Fraser
Post by Rainer Weikusat
Post by Alex Fraser
Post by d-fan
How can I open a socket connection with a timeout?
[...]
Post by Alex Fraser
the easy, unreliable way to enforce a shorter timeout is alarm(3).
What makes alarm() unreliable?
I was being too imprecise. The 'easy, unreliable timeout' is setting
up a no-op handler for SIGALRM and relying on the alarm signal to
interrupt the connect. The problem is that 'setting up an alarm' and
'starting to connect' are two operations instead of one atomic
operation and their can be a near arbitrary delay between them because
other processes could be scheduled. This means there is a chance that
the SIGALRM may actually be posted to the process before the connect
ever blocks.
But you'd have the same "near arbitrary delay" even if there was an
atomic "connect() with timeout" call, between timeout/connect success
and the thread being scheduled again. So are you any worse off?
"Well, a piece of orbital junk could smash the building you are living
in at any time so it would clearly be useless to prevent it from
burning down by not making a large fire in the living room before
leaving for a three week holiday trip."

Relying on (a single) SIGALRM to interrupt a blocked system call could
lead to a lost wakeup in particular circumstances. This potential
problem can be avoided by suitable code, ie by longjumping from the
handler instead. This still doesn't mean that connect was ever
actually called, but that the program has done every possible thing to
regain control after the timeout expired. Which in no way implies that
some other problem could not cause a similar effect.

Continue reading on narkive:
Loading...