What can cause a CFSocket to close itself? - objective-c

I have a class method which requires an underlying CFSocket, and this method gets called very often so it's too expensive to create and destroy a new socket each time the method runs. So instead I've created a static instance of a CFSocketRef so I can share a single socket between method calls:
+(void)myStaticMethod {
static CFSocketRef udpSocket;
#synchronized(self) {
if (!udpSocket) {
udpSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, NULL, NULL);
int yes = 1;
setsockopt(CFSocketGetNative(udpSocket), SOL_SOCKET, SO_NOSIGPIPE, (void *)&yes, sizeof(yes));
}
}
//method body
}
I have two questions:
Do I have to worry about destroying (invalidating) the socket when the app will terminate, or does it close itself?
Which events might cause the socket to close itself and how would you prevent potentially writing to a bad CFSocketRef?

If an app really terminates then all resources, including sockets, are released. But normally apps don't terminate but go into the background and in that case the socket can become invalid. This is described quite well in Technical Note TN2277. See in particular the section "Data Socket".
Since the creation of an UDP socket is a simple operation, the following advice from TN2277 would apply to your code:
If reopening your data socket is simple, cheap, and has no user
visible consequences, the best approach is to close the socket when
the app goes into the background, and reopen it when it comes back
into the foreground. This makes your life very simple; in fact, if you
do this, you can ignore the rest of this section entirely!

Related

NUnit async test causing AppDomainUnloadedException

I have a .NET 4.5 WCF service with async operations. I have integration tests which constructs the service host using NetNamedPipeBinding and hits the operation via a client.
However, each test like this always causes NUnit to report the following:
System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
This can happen if the test(s) started a thread but did not stop it.
Make sure that all the threads started by the test(s) are stopped before completion.
Everything looks ok to me. Can anyone see what might be causing this? I have a complete code sample on GitHub: https://github.com/devlife/codesamples
I'm having the same problem. It looks as if the issue are "lenient" completion port threads (in the ThreadPool) that have been used by WCF to handle async IO.
When ServiceHost.Close() is used, it will signal all those threads that work is done, but they won't go away immediately, that is, they may outlive the end of the ServiceHost.Close() operation. Thus, the "shutdown" procedure races with the actual AppDomain unloading induced by NUnit due to the end of the test run.
Basically, a simple Thread.Sleep(<a couple of seconds>) after a ServiceHost.Close() "fixes" this :-)
After much searching around on the internet I couldn't find a robust solution for this issue (for a selection of similar issues, not all due to the same cause though, google "unit test appdomainunloadedexception"), short of having some way to suppress this warning itself.
I tried different bindings and transports (includind the NullTransport), but to no avail.
In the end I settled with this "solution":
static void PreventPrematureAppDomainUnloadHack()
{
//
// When NUnit unloads the test AppDomain, the WCF started IO completion port threads might
// not have exited yet.
// That leads to AppDomainUnloadedExceptions being raised after all is said and done.
// While native NUnit, ReSharper oder TestDriven.NET runners don't show these, VSTest (and
// TFS-Build) does. Resulting in very annoying noise in the form of build/test warnings.
//
// The following code _attempts_ to wait for all completion port threads to end. This is not
// an exact thing one can do, however we mitigate the risk of going wrong by several factors:
// (1) This code is only used during Unit-Tests and not for production code.
// (2) It is only called when the AppDomain in question is about to go away anway.
// So the risk of someone starting new IO threads while we're waiting is very
// low.
// (3) Finally, we have a timeout in place so that we don't wait forever if something
// goes wrong.
//
if (AppDomain.CurrentDomain.FriendlyName.StartsWith("test-domain-", StringComparison.Ordinal))
{
Console.WriteLine("AppDomainUnloadHack: enabled (use DbgView.exe for details).");
Trace.WriteLine(string.Format("AppDomainUnloadHack: enabled for domain '{0}'.", AppDomain.CurrentDomain.FriendlyName));
AppDomain.CurrentDomain.DomainUnload += (sender, args) =>
{
int activeIo;
var sw = Stopwatch.StartNew();
var timeout = TimeSpan.FromSeconds(3);
do
{
if (sw.Elapsed > timeout)
{
Trace.WriteLine("AppDomainUnloadHack: timeout waiting for threads to complete.");
sw.Stop();
break;
}
Thread.Sleep(5);
int maxWorkers;
int availWorkers;
int maxIo;
int availIo;
ThreadPool.GetMaxThreads(out maxWorkers, out maxIo);
ThreadPool.GetAvailableThreads(out availWorkers, out availIo);
activeIo = maxIo - availIo;
Trace.WriteLine(string.Format("AppDomainUnloadHack: active completion port threads: {0}", activeIo));
} while (activeIo > 0);
Trace.WriteLine(string.Format("AppDomainUnloadHack: complete after {0}", sw.Elapsed));
};
}
}
The timeout of 3 seconds is totally arbitrary and so is the wait of 5ms between each retry. Sometimes I do get a "timeout", but most of the time it works.
I make sure that this code is called once for every test assembly (i.e. through a static ctor of a referenced type).
As usual in such cases YMMV.

WinRT HttpClient blocks splashcreen

I do asynchronous requests in LoadState method of a certain Page. I use HttpClient to make a request and I expect the splashscreen to go away while I await the result.
If I am not connected to any networks, the splashscreen immediately goes away and I get a blank page because the request obviously didn't happen.
But if I am connected to a network but have connectivity issues (for example, I set a wrong IP address) it seems to start a request and just block.
My expectation was that the HttpClient would realize that it cannot send a request and either throw an exception or just return something.
I managed to solve the issue of blocking by setting a timeout of around 800 milliseconds, but now it doesn't work properly when the Internet connection is ok. Is this the best solution, should I be setting the timeout at all? What is the timeout that's appropriate which would enable me to differentiate between an indefinitely blocking call and a proper call that's just on a slower network?
I could perhaps check for Internet connectivity before each request, but that sounds like an unpredictable solution...
EDIT: Now, it's really interesting. I have tried again, and it blocks at this point:
var rd = await httpClient.SendAsync(requestMsg);
If I use Task.Run() as suggested in the comments and get a new Thread, then it's always fine.
BUT it's also fine without Task.Run() if there is no Internet access but the network access is not "Limited" (it says that the IPv4 connectivity is "Internet access" although I cannot open a single website in a browser and no data is returned from the web service. It just throws System.Net.Http.HttpRequestException which was something I was expecting in the first place) Only blocks when the network connection is Limited.
What if instead of setting a timeout, you checked the connection status using
public static bool IsConnected
{
get
{
return NetworkInformation.GetInternetConnectionProfile() != null;
}
}
This way if IsConnected, then you make the call; otherwise, ignore it.
I'm not sure if you are running this in App.xaml.cs? I've found requests made in that class can be fickle and it may be best to move the functionality to an extended splash screen to ensure the application makes it all the way through the activation process.
http://msdn.microsoft.com/en-us/library/windows/apps/xaml/Hh868191(v=win.10).aspx

How to fix naive server implementation with CFSocket to allow multiple connections

I have been studying the bonjour/NSStream sample code from lecture #17 of Stanford's CS193p course (iOS programming) on iTunes U from the winter of 2010. The example code is available here.
In a nut shell, the sample code creates a socket and binds to port 0 so that it will be given a free port. It then publishes a service with that port using NSNetService (bonjour). An NSNetServiceBrowser is also started when the app starts up. Available services are placed in a UITableView. When a cell is selected, the corresponding service is resolved, an NSOutputStream is created, and data can be sent.
This is a naive implementation because connections are rejected if a connection already exists. My question is, what is the proper way to handle multiple connections? Once multiple clients are connected to the server, how does the server distinguish between them? i.e. How can data be sent specifically to one client and not the others?
- (void) _acceptConnection:(int)fd
{
int junk;
// If we already have a connection, reject this new one. This is one of the
// big simplifying assumptions in this code. A real server should handle
// multiple simultaneous connections.
if ( self.isReceiving ) {
junk = close(fd);
assert(junk == 0);
} else {
[self _startReceive:fd];
}
}
// Called by CFSocket when someone connects to our listening socket.
// This implementation just bounces the request up to Objective-C.
static void AcceptCallback(CFSocketRef s,
CFSocketCallBackType type,
CFDataRef address,
const void *data,
void *info)
{
ReceiveServer * obj;
assert(type == kCFSocketAcceptCallBack);
assert(data != NULL);
obj = (ReceiveServer *) info;
assert(obj != nil);
assert(s == obj->_listeningSocket);
[obj _acceptConnection:*(int *)data];
}
I'm not specifically familiar with that course or sample code, but: separate out the code for handling a connection into a different class from the code which accepts new connections. So, in the posted code, you'd move the -startReceive: method and everything which it calls to another class.
Then, each time a connection is accepted, create an instance of that other class. That instance will be responsible for processing all of the communication on that connection. It will be given the information about the connection (mainly the fd) during initialization. The main controller object of the server could hold those instances in an array.
Where things go from here will depend on what your server actually does. At the very least, your connection objects will need to inform the main controller object when they are closed, so the main controller can remove them from the array. You can use notifications or the delegate pattern for that.

Objective-C: Avoiding EXCEPTIONS when NSConnection to Distributed Objects fail

I'm using Objective-C Distributed Objects (DO) to share data from one application (that collects data from the network) to another (a patch inside Quartz Composer). When the connection to the distant object fails (when I shut down the first application), I'm get:
5/16/12 8:17:06.373 PM Quartz Composer: *** EXCEPTION IGNORED: connection went invalid while waiting for a reply because a mach port died
After that point, the Quartz composition is hung. Even after I bring the first application back up, it's still hung. I want the Quartz patch to reconnect.
I am using the Notification Center to put shut down the old objects, like this:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(connectionDidDie)
name:NSConnectionDidDieNotification
object:theConnection];
Right now, my counnectionDidDie looks like this:
- (void) connectionDidDie
{
NSLog(#"Connection died and we detected it");
[[self proxyObject] release];
[self setProxyObject:nil];
theConnection = nil;
}
I also check to be sure the connection is still alive, just before accessing any part of the proxyObject, like this:
if ([NSConnection defaultConnection]) { // this line triggers the exception
// access proxyObject
}
I've also tried
if ([theConnection isValid]) { // this line triggers the exception
// access proxyObject
}
In both cases, it's this test that triggers this EXCEPTION.
What can I do to prevent the hang of Quartz when I shutdown the first application, who has the vended object?
I was never able to find a way to shut down the DO connection fast enough to prevent QC, who draws as 30-60 frames per second, front testing the connection (and crashing) before connectionDidDie: was called. Ultimately, I've decided to use DO, only to get an initial copy of the object, which then do a deep copy of, and then kill the DO connection while nothing is trying to access it. DO just doesn't seem to be that great of solution, after you dig into it. :(

problem with asynchronous programming while calling 2 methods in Objective-C

Inside ClassA:
-(void)authenticateUser
{
authenticate_Obj = [classB_Obj authenticateMobileUser];
}
Inside ClassB:
-(AuthenticateObj*)authenticateMobileUser
{
[mobile_Obj AuthenticateMobileServer:self action:#selector(Handler:)];
return authenticate_G_Obj;
}
-(void)Handler:(id)value
{
authenticate_G_Obj = (AuthenticateObj*)value;
}
Now once the authenticateMobileUser method of classB returns the controll back to ClassA, we will get the Object authenticate_Obj initiated.
My problem is , when i run the project the authenticate_Obj is NULL... actually when it enters the handler method , the Object is initiallized. but the controlled is returned back to ClassA, without entering into Handler method. I guess this is the problem of Asynchronous execution.
How to make it enter into handler method and then only return the controll to ClassA??
Plz help me..
Thank You.
It sounds like what you think you want to do is to block execution until authentication completes. This might be possible if AuthenticateMobileServer spawns a background thread to work in -- you'd use a synchronisation object such as NSLock -- but it's really a Bad Idea. Why have a background thread at all if you're going to block anyway? And thread synchronisation is notoriously tricky and prone to errors if you don't know what you're doing, which (let's face it) you don't.
Instead, you probably should accept that there will be a period of uncertainty while the authentication takes place, during which your app should keep processing in some intermediate state, and then use a callback to notify you when the authentication is complete and you can then go on with whatever it is you need to do with the authenticated user.
There are a bunch of ways you could do this, and there's not enough detail in the question to say exactly which would be best. But you already seem to be using something very similar within ClassB, so I'd say do the same from ClassA:
Inside ClassA:
-(void)authenticateUser
{
authenticate_Obj = nil;
[classB_Obj authenticateMobileUserAndNotify:self action:#selector(authenticatedObject:)];
// returns more or less immediately, not yet authenticated
}
-(void)authenticatedObject:(YourAuthObjectClass*) authObj
{
authenticate_Obj = authObj;
// do post-authentication stuff here
}
Inside ClassB:
-(void)authenticateMobileUserAndNotify:(id)target action:(SEL)sel
{
// I'm making these ivars for simplicity, there might be other considerations though
callbackTarget = target;
callbackSelector = sel;
[mobile_Obj AuthenticateMobileServer:self action:#selector(Handler:)];
}
-(void)Handler:(id)value
{
authenticate_G_Obj = (AuthenticateObj*)value;
[callbackTarget performSelectorOnMainThread:callbackSelector withObject:authenticate_G_Obj waitUntilDone:NO];
}
Obviously this is just a sketch and not intended to be used as is. And you'll need to consider what goes on in your app while in the waiting state, with authentication in progress but authenticate_Obj still nil. But hopefully you get the idea.
I think you are saying that AuthenticateMobileServer:action: is asynchronous and you want to block until it's finished so you can get the return value. Unfortunately, we can't really tell you without knowing how it works. The main question is does it run the Handler action on the main thread or a secondary thread.
If it runs the action on the main thread, the best strategy is to return immediately from authenticateMobileUser without waiting for the authentication object and disable the UI elements that depend on being authenticated. Then later when you get the authentication object, you should re-enable the UI elements.
If it runs the action on a background thread, the easiest thing is to set up another method similar to Handler (by the way, the naming convention for methods and variables is to start with lower case), which you then invoke from Handler with performSelectorOnMainThread:waitUntilDone:. You can then use the same strategy as outlined above.
Both answers of JeremyP and walkytalky are correct and go at the heart of creating a respondsive UI. The rule of thumb:
If you doing potentially blocking operations such as networking on the main thread, you will get in trouble.
There are at least two reasons:
you are blocking the run loop so it cannot process user events anymore. This will result in a spinning beachball on the mac and a unresponsive UI on both mac and iOS.
If you are on iOS, there is a watchdog going around and checking if your UI is still responding to user events. If you are blocking the UI longer than I think 20s you will be terminated with the error code 0x8badf00d.
So to get this things done which maybe take some time you have to do it on the background thread. As the two answers of JeremyP and walkytalky point out often you get a callback. That is fine but there are in total three ways of messaging:
Delegation
Notifications
Kev-value-observing
All three can be and are used. There are subtle differences between them. One of the most important is that delegation is a 1:1 messaging whereas the other to are a 1:n messaging.
Now that said do not think that you have to use NSThread. Have a look at NSOperation and NSOperationQueue instead. They allow to encapsulate pieces of work in an operation and let them run on a queue in the background. Also if you are using these callbacks with the #selector(methodname:) syntax there is something new: blocks. Often there are equivalent methods which take a block instead of a selector to be executed as a callback.
To finish here is the golden rule:
You may update your model on the background thread, but NEVER update your UI on a background thread.
Check out the WWDC10 videos about these topics. There is a great 2-part talk about networking which explains the concepts in detail.