Using threads to set a timeout on a connect() call

Member
Posts: 70
Joined: 2004.06
Post: #1
I am trying to make a socket connect() call timeout after a set period of time, rather than just sitting there doing nothing for hours if it is unable to connect. I was told to use setsockopt() with SO_SNDTIMEO and SO_RCVTIMEO to set a timeout, but as I expected it didn't affect the connect call.

My first thought after that was to set some sort of alarm, but because connect() just blocks if it can't make the connection, the entire thread locks up and I can't do anything until connect returns. A timer or alarm won't help me much.

So I decided to use multiple threads, and just terminate the connecting thread if it was taking too long. As I'm using Cocoa, I tried to use NSThread to do it but that doesn't appear to have a way to check the status of threads after they have been created. I could use POSIX threads, but that will get a little messy because it is with Obj-C classes.

Now for the questions: am I on the right track using threads to timeout, or am I just being stupid and missing another obvious solution? Have I missed something with NSThread that will allow me to track a threads progress and terminate it as necessary? And finally, if NSThread is as inflexible as I understand it to be (which I doubt), what alternatives are available? I've got no problem with writing my own threading class like NSThread, it would only have to be a wrapper for the POSIX calls. But I'd rather not Smile
Quote this message in a reply
Member
Posts: 70
Joined: 2002.07
Post: #2
I just noticed this thread; I'm about a month late to answer this Smile I'm knee-deep in dim3 networking, and this is a problem I ran into.

By the docs, the recommended way is to set the socket to non-blocking, call the connect, then use poll to wait for the socket to come up OK to write.

There's all sorts of weirdness associated with this if you are thinking cross platform (because of how each system reports errors.) Also, the code is kind of messy as you have to check for a million different permutations of errno while you do this, etc etc.

Or, since it's probably just for a game, the simple solution (which I use) is just to set an alarm. If the alarm goes off during the connect, the connect goes into the background (same with non-blocking) and cancels out with an error.

Look at the man pages for alarm.

[>] Brian
Quote this message in a reply
Member
Posts: 70
Joined: 2004.06
Post: #3
I've written myself a socket class in Obj-C now, and I call the connect function in a separate thread, which seems to work acceptably.

It has its problems too though, if the connect fails then I just abandon the thread which seems incredibly messy and dangerous. But whatever, it seems to work alright Smile
Quote this message in a reply
Member
Posts: 370
Joined: 2002.04
Post: #4
I don't know if this works on blocking system calls, but if it does you could use alarm() and catch the SIGALRM and then act appropriately...

Did you ever wonder why we had to run for shelter when the promise of a brave new world unfurled beneath the clear blue sky?
Quote this message in a reply
Member
Posts: 70
Joined: 2004.06
Post: #5
To do what? Terminate the dead thread or kill the failed connect() call?
Quote this message in a reply
Member
Posts: 370
Joined: 2002.04
Post: #6
Anything you want, up to and including calling system("kill -9 -1")...

Did you ever wonder why we had to run for shelter when the promise of a brave new world unfurled beneath the clear blue sky?
Quote this message in a reply
Member
Posts: 70
Joined: 2002.07
Post: #7
SOUR-Monkey Wrote:To do what? Terminate the dead thread or kill the failed connect() call?

The problem with connects is that there is a system-level time out, and it's not something you'd want to change (I don't think it's even changeable on OS X). The real way to do this is to put the connect in non-blocking, BUT, even then, if you stop using the socket it will STILL continue to try to connect until the timeout.

Using alarm (this is what I was talking about) is an easy way around this (but not the recommended way.) Remember, the connect will still continue, but you can just close the socket and forget about it.

Basically, if an alarm throws, catch it with an empty function and this will essentially "cancel" the connect (i.e., the connect function will return.)

Check out alarm man page. Some pseudo code:

.... the handler

void sigalarm_handler(int sig)
{
}

.... your connect function ....

signal(SIGALRM,sigalarm_handler);
alarm(your_time_out_in_seconds);

err=connect(.....);

alarm(0);

alarm(0) turns off the alarm. If the connect takes longer than "your_time_out_in_seconds", the alarm will fire and the connect will immediately return with an error.

I do this in dim3 networking.

[>] Brian
Quote this message in a reply
Post Reply 

Possibly Related Threads...
Thread: Author Replies: Views: Last Post
  CoreAnimation call from UIKit causing mysterious crash funkboy 2 3,391 Jul 21, 2012 03:28 PM
Last Post: funkboy
  Connect to Server from Iphone BugSniper 6 9,466 Jul 15, 2009 04:57 PM
Last Post: BugSniper
  The need for connect/listen on raw sockets? BinarySpike 28 15,898 Oct 26, 2006 07:23 PM
Last Post: akb825
  Threads, Networks, and Performance. BinarySpike 6 4,778 Jan 7, 2005 10:34 PM
Last Post: BinarySpike