Networking Forums

Networking Forums > Computer Networking > Linux Networking > use alarm() to achieve timeout.

Reply
Thread Tools Display Modes

use alarm() to achieve timeout.

 
 
guanghui
Guest
Posts: n/a

 
      12-16-2008, 02:57 AM
hello to all,
I am now reading UNP(unix network programming). Here is an excerpt
from the book talking about achieving timeout using alarm() when doing
a socket i/o.

alarm(5); // its signal handler is just used to interrupt recvfrom( )
if((n=recvfrom(sockfd,recvline,MAXLINE,0,NULL,NULL ))<0){
if(errno==EINTR)
fprintf(stderr,"socket time out\n");
else
err_sys("recvfrom error");
}

what I'm confused is , because alarm and recvfrom is not atmoic, so
there is a window between them. When the system is really heavyloaded,
it's possible the following things would happen:
1 alarm(5)
2 other processed got executed
3 our program is executed again, and recvfrom is going to be
called, but
exactly before recvfrom is called, the SIGALRM is generated
and its signal
handler is called, but the handler doesn't interrupt
recvfrom because
recvfrom hasn't yet been called. the recvfrom got called and
because the
alarm has expired so possibly we would block forever.

Is this something we couldn't avoid in case the system is heavyloaded,
or there is a way to solve this?

Thanks.(sorry for my poor english)
 
Reply With Quote
 
 
 
 
David Schwartz
Guest
Posts: n/a

 
      12-16-2008, 03:52 AM
On Dec 15, 7:57*pm, guanghui <hellog...@163.com> wrote:

> alarm(5); // its signal handler is just used to interrupt recvfrom( )
> if((n=recvfrom(sockfd,recvline,MAXLINE,0,NULL,NULL ))<0){
> * *if(errno==EINTR)
> * * * *fprintf(stderr,"socket time out\n");
> * *else
> * * * * *err_sys("recvfrom error");
>
> }


> what I'm confused is , because alarm and recvfrom is not atmoic, so
> there is a window between them. When the system is really heavyloaded,
> it's possible the following things would happen:
> * * * *1 alarm(5)
> * * * *2 other processed got executed
> * * * *3 our program is executed again, and recvfrom is going to be
> called, but
> * * * * * exactly before recvfrom is called, the SIGALRM is generated
> and its signal
> * * * * * handler is called, but the handler doesn't interrupt
> recvfrom because
> * * * * * recvfrom hasn't yet been called. the recvfrom got called and
> because the
> * * * * * alarm has expired so possibly we would block forever.
>
> Is this something we couldn't avoid in case the system is heavyloaded,
> or there is a way to solve this?


Your alarm handler should have handled the alarm, preventing the
'recvfrom' from ever getting called. If your alarm handler allowed the
control flow to go and call 'recvfrom', then it failed to handle the
problem.

DS
 
Reply With Quote
 
guanghui
Guest
Posts: n/a

 
      12-16-2008, 04:13 AM
On Dec 16, 12:52*pm, David Schwartz <dav...@webmaster.com> wrote:
> On Dec 15, 7:57*pm, guanghui <hellog...@163.com> wrote:
>
>
>
>
>
> > alarm(5); // its signal handler is just used to interrupt recvfrom( )
> > if((n=recvfrom(sockfd,recvline,MAXLINE,0,NULL,NULL ))<0){
> > * *if(errno==EINTR)
> > * * * *fprintf(stderr,"socket time out\n");
> > * *else
> > * * * * *err_sys("recvfrom error");

>
> > }
> > what I'm confused is , because alarm and recvfrom is not atmoic, so
> > there is a window between them. When the system is really heavyloaded,
> > it's possible the following things would happen:
> > * * * *1 alarm(5)
> > * * * *2 other processed got executed
> > * * * *3 our program is executed again, and recvfrom is going to be
> > called, but
> > * * * * * exactly before recvfrom is called, the SIGALRM is generated
> > and its signal
> > * * * * * handler is called, but the handler doesn't interrupt
> > recvfrom because
> > * * * * * recvfrom hasn't yet been called. the recvfrom got called and
> > because the
> > * * * * * alarm has expired so possibly we would block forever.

>
> > Is this something we couldn't avoid in case the system is heavyloaded,
> > or there is a way to solve this?

>
> Your alarm handler should have handled the alarm, preventing the
> 'recvfrom' from ever getting called. If your alarm handler allowed the
> control flow to go and call 'recvfrom', then it failed to handle the
> problem.
>
> DS- Hide quoted text -
>
> - Show quoted text -


sorry, I think I forgot something.
the signal handler is registered with sa_flags |=SA_INTERRUPT;
and the following is the hander:
void sig_alrm(int signo)
{
return; /* just interrupt the recvfrom() */
}
and when data arrived before SIGALRM is generated , we simply
turn off the alarm using alarm(0);

what I really mean is "alarm( ) and recvfrom( )" should be an
atomic operation, when SIGALRM is generated and caught,
the program is blocked inside the recvfrom system call so
the handler would interrupt recvfrom( ).
 
Reply With Quote
 
David Schwartz
Guest
Posts: n/a

 
      12-16-2008, 03:18 PM
On Dec 15, 9:13*pm, guanghui <hellog...@163.com> wrote:

> sorry, I think I forgot something.
> the signal handler is registered with sa_flags |=SA_INTERRUPT;
> and the following is the hander:
> void sig_alrm(int signo)
> {
> * * *return; * * /* just interrupt the recvfrom() */}


There's your bug. How do you know that will interrupt the 'recvfrom'?

> and when data arrived before SIGALRM is generated , we simply
> turn off the alarm using * alarm(0);
>
> what I really mean is "alarm( ) and recvfrom( )" should be an
> atomic operation, when SIGALRM is generated and caught,
> the program is blocked inside the recvfrom system call so
> the handler would interrupt recvfrom( ).


You are correct, they should be atomic. However, your code doesn't
make them behave atomically, so your code is broken.

The correct fix is for the signal handler to *HANDLE* the signal, not
just ignore it. Handling the signal requires ensuring that the program
control flow does not go the wrong way.

DS
 
Reply With Quote
 
helloghui@gmail.com
Guest
Posts: n/a

 
      12-17-2008, 02:27 AM
On Dec 17, 12:18 am, David Schwartz <dav...@webmaster.com> wrote:
> On Dec 15, 9:13 pm, guanghui <hellog...@163.com> wrote:
>
> > sorry, I think I forgot something.
> > the signal handler is registered with sa_flags |=SA_INTERRUPT;
> > and the following is the hander:
> > void sig_alrm(int signo)
> > {
> > return; /* just interrupt the recvfrom() */}

>
> There's your bug. How do you know that will interrupt the 'recvfrom'?
>
> > and when data arrived before SIGALRM is generated , we simply
> > turn off the alarm using alarm(0);

>
> > what I really mean is "alarm( ) and recvfrom( )" should be an
> > atomic operation, when SIGALRM is generated and caught,
> > the program is blocked inside the recvfrom system call so
> > the handler would interrupt recvfrom( ).

>
> You are correct, they should be atomic. However, your code doesn't
> make them behave atomically, so your code is broken.
>
> The correct fix is for the signal handler to *HANDLE* the signal, not
> just ignore it. Handling the signal requires ensuring that the program
> control flow does not go the wrong way.
>
> DS


Thanks for your reply. So you mean what I concern is right and the
implementation of timeout using alarm() from
UNP(<<unix network programming ,3rd, by Richard stevens>>)
is not perfect(the code I wrote above is from UNP)
just because of the small window between alarm() and recvfrom().
then could you please show me a correct solution to implement
timeout using alarm() when doing socket i/o?
 
Reply With Quote
 
Johannes Bauer
Guest
Posts: n/a

 
      12-17-2008, 03:48 AM
(E-Mail Removed) schrieb:

> Thanks for your reply. So you mean what I concern is right and the
> implementation of timeout using alarm() from
> UNP(<<unix network programming ,3rd, by Richard stevens>>)
> is not perfect(the code I wrote above is from UNP)
> just because of the small window between alarm() and recvfrom().
> then could you please show me a correct solution to implement
> timeout using alarm() when doing socket i/o?


I believe there is no safe way of implementing what you want using
alarm(2). Why do you want to use alarm anyways? Have you thought about
poll? It seems much more like what you want.

Regards,
Johannes

--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verlästerung von Gott, Bibel und mir und bewusster Blasphemie."
-- Prophet und Visionär Hans Joss aka HJP in de.sci.physik
<48d8bf1d$0$7510$(E-Mail Removed)>
 
Reply With Quote
 
helloghui@gmail.com
Guest
Posts: n/a

 
      12-17-2008, 12:56 PM
On Dec 17, 12:48 pm, Johannes Bauer <dfnsonfsdu...@gmx.de> wrote:
> hellog...@gmail.com schrieb:
>
> > Thanks for your reply. So you mean what I concern is right and the
> > implementation of timeout using alarm() from
> > UNP(<<unix network programming ,3rd, by Richard stevens>>)
> > is not perfect(the code I wrote above is from UNP)
> > just because of the small window between alarm() and recvfrom().
> > then could you please show me a correct solution to implement
> > timeout using alarm() when doing socket i/o?

>
> I believe there is no safe way of implementing what you want using
> alarm(2). Why do you want to use alarm anyways? Have you thought about
> poll? It seems much more like what you want.
>
> Regards,
> Johannes
>
> --
> "Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
> verlästerung von Gott, Bibel und mir und bewusster Blasphemie."
> -- Prophet und Visionär Hans Joss aka HJP in de.sci.physik
> <48d8bf1d$0$7510$54022...@news.sunrise.ch>


yes,I think poll or select is an excellent solution to achieve timeout
when doing socket i/o. But the way using alarm() made me think a
lot.
 
Reply With Quote
 
David Schwartz
Guest
Posts: n/a

 
      12-17-2008, 05:42 PM
On Dec 16, 7:27*pm, hellog...@gmail.com wrote:

> Thanks for your reply. So you mean what I concern is right and the
> implementation of timeout using alarm() from
> UNP(<<unix network programming ,3rd, by Richard stevens>>)
> is not perfect(the code I wrote above is from UNP)


You are correct. That code has a race condition.

> *just because of the small window between alarm() and recvfrom().
> then could you please show me a correct solution to implement
> timeout using alarm() when doing socket i/o?


I don't have the code handy, but the basic idea is to have the signal
handler call longjmp. You only call the function you want to timeout
if 'setjmp' returns zero. Since the signal handler calls 'longjmp',
the signal handler will ensure 'setjmp' does not return zero. So there
is no way you can call 'recvfrom' (or whatever) after the signal has
fired.

DS
 
Reply With Quote
 
helloghui@gmail.com
Guest
Posts: n/a

 
      12-18-2008, 01:17 PM
On Dec 18, 2:42 am, David Schwartz <dav...@webmaster.com> wrote:
> On Dec 16, 7:27 pm, hellog...@gmail.com wrote:
>
> > Thanks for your reply. So you mean what I concern is right and the
> > implementation of timeout using alarm() from
> > UNP(<<unix network programming ,3rd, by Richard stevens>>)
> > is not perfect(the code I wrote above is from UNP)

>
> You are correct. That code has a race condition.
>
> > just because of the small window between alarm() and recvfrom().
> > then could you please show me a correct solution to implement
> > timeout using alarm() when doing socket i/o?

>
> I don't have the code handy, but the basic idea is to have the signal
> handler call longjmp. You only call the function you want to timeout
> if 'setjmp' returns zero. Since the signal handler calls 'longjmp',
> the signal handler will ensure 'setjmp' does not return zero. So there
> is no way you can call 'recvfrom' (or whatever) after the signal has
> fired.
>
> DS


I think the following is possibly a correct solution


static sigjmp_buf jmpbuf;// global data

{//inside a function
...
struct sigaction act;
act.sa_handler=sig_alrm;
sigemptyset(&act.sa_mask);
act.sa_flags=0;
// now we do not need the following line
// because we're using siglongjmp
// act.sa_flags |=SA_INTERRUPT;
sigaction(SIGALRM,&act,NULL);

if(sigsetjmp(jmpbuf,1)){
printf("timeout when trying to read\n");
} else{
alarm(5);// will timeout in 5 seconds
recvfrom(...);
alarm(0);// turn off the alarm
}
...
}

void sig_alrm(int signo)
{
siglongjmp(jmpbuf,1);
}
 
Reply With Quote
 
Johannes Bauer
Guest
Posts: n/a

 
      12-18-2008, 03:29 PM
(E-Mail Removed) schrieb:

> I think the following is possibly a correct solution


[...]

> alarm(5);// will timeout in 5 seconds
> recvfrom(...);
> alarm(0);// turn off the alarm



No, it isn't. It also has a race condition: After a successful read but
before the alarm(0) the SIGALRM can occour resulting in you thinking
there's a timeout when there isn't.

You really ought to go with poll(2) instead of that error-prone,
difficult-to-decipher setjmp stuff.

Regards,
Johannes

--
"Meine Gegenklage gegen dich lautet dann auf bewusste Verlogenheit,
verlästerung von Gott, Bibel und mir und bewusster Blasphemie."
-- Prophet und Visionär Hans Joss aka HJP in de.sci.physik
<48d8bf1d$0$7510$(E-Mail Removed)>
 
Reply With Quote
 
 
 
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
How to achieve super low TCP latency? Ignoramus446 Linux Networking 5 03-28-2011 07:07 PM
Configure ARP-Request-Timeout? (NOT Cache-Timeout!) Mario lzteM Linux Networking 0 07-28-2008 09:41 AM
Please help achieve a Ban on Primate testing in Europe from_tgs@myway.com Broadband 5 08-25-2007 05:15 PM
How to Achieve Wireless Security? Anton Wireless Networks 6 11-10-2004 06:04 AM
Complete newbie to networking: What I want to achieve! Tone-EQ Home Networking 17 04-27-2004 08:19 AM



1 2 3 4 5 6 7 8 9 10 11