I'm trying to debug a multithreaded app in Eclipse. There are 3 Threads
Read
Write
Controller
Read and Write both access a method in Controller. I am trying to debug a problem when Write executes that Controller method.
I've got a breakpoint set in the Write thread and the Controller. I break in Write and I turn off my network connection to simulate my error and hit resume so I wind up at my breakpoint in Controller.
When I'm there Controller works as it should: it kills the Read and Write threads (I think) and starts new Read and Write threads. After killing Read and Write, I turn on my network connection to simulate the problem being solved.
All this is great. What should happen now is everything continues on its merry way. Except what really happens is the Read thread executes and I wind up hitting the breakpoint I set in Controller again - the same one I previously hit from Write. To make matters worse, it still thinks the network connex is unavailable - which makes no sense as I've re-enabled it.
This all makes me wonder if I need to stop the Read thread from executing somehow. Do I need to suspend it via Eclipse? Is it even possible to kill a thread from an app running in the debugger?
Mark
Do I need to suspend it via Eclipse?
No there is no need to suspend a thread in order that you code works. I suspend rarely I thread, I do it when I suspect that is waiting for something I don't except. I use breakpoints to control the stop and sometimes with properties. Here is an interresting answer.
Is it even possible to kill a thread from an app running in the debugger?
No and if it was possible, it will not be a good idea regarding the current specifications of Java. A good method to stop a thread is to use a flag to exit from the run() method properly : see here
Are you sure that you exit from you Read and Write threads ? One way is to add debug info in you run method :
run()
{
System.out.println("start : " + this.getName());
// do your process
System.out.println("stop : " + this.getName());
}
Logging is sometimes easier than debugging in multithreading. It is difficult to be more specific without the code.
Related
I have a Mac OS X app and I want to detect or catch the event when the user Force Close my app.
At first I thought applicationWillTerminate will do the work but it didn't:
func applicationWillTerminate(_ aNotification: Notification) {
print("applicationWillTerminate called")
}
Do you have any idea how can I do that?
Major credit goes to #caseynolan for putting work in here to come up with an answer. Unfortunately, there are, in fact, some major issues with the suggested approach.
First, signal handlers are per-process. There are other, legitimate uses of signals, and installing handlers will negatively impact their behavior without very careful work.
Second, signals interrupt a thread, and that thread can be doing anything, including holding locks. Examples of things that hold locks - malloc/free, the Objective-C runtime.
This is an part of a class of problems known as "async safety". If you check out "man sigaction" (note, sigaction is a much improved API over signal) you see that there are actually a very small number of functions that are safe to call from a signal handler. Calling unsafe functions, like NSLog, will sometimes work. But, will also sometimes deadlock, depending on what the thread was doing at the time.
Now, I will admit that my experience with signals does not include use of SIGTERM. However, since it can be delivered at any time, it still will be subject to async safety issues, even thought it is not a crash.
In short: it is almost certainly unsafe to run your code in a signal handler, and it will deadlock sometimes. And, those deadlocks will occur during unpredictable points of its execution.
Third, there are fatal events that aren't mapped to signals, on top of SIGKILL. This may not matter to do, depending on how strong a guarantee you need about detecting your process termination.
What I'd do Instead:
I think you're only safe option is to use a sentinel process. The idea is you start up a child process, and in that child, observe the parent. If/when that process disappears, you can then execute your code.
This is a safe, deadlock-risk free way to monitor for arbitrary process exits. However, it could be challenging to move your operations out-of-process. Unfortunately, I believe that's a necessary aspect of this, if you want it to be reliable.
Good luck!
Disclaimer: I'm not an expert, and researching for this post has stretched the limits of my rusty C/Objective-C knowledge. I don't know how the following code is viewed by Apple for submissions to the App Store, so YMMV.
The following has been shamelessly ripped from Wikipedia and reworked:
#import <Foundation/Foundation.h>
/**
This will handle signals for us, specifically SIGTERM.
*/
void handleSignal(int sig) {
if (sig == SIGTERM) {
// Caught a SIGTERM
}
/*
SIGTERM is a clear directive to quit, so we exit
and return the signal number for us to inspect if we desire.
We can actually omit the exit(), and everything
will still build normally.
If you Force Quit the application, it will still eventually
exit, suggesting a follow-up SIGKILL is sent.
*/
exit(sig);
}
/**
This will let us set a handler for a specific signal (SIGTERM in this case)
*/
void setHandler() {
if (signal(SIGTERM, handleSignal) == SIG_ERR) {
NSLog(#"Failed to set a signal handler.");
} else {
NSLog(#"Successfully set a signal handler.");
}
}
Call only asynchronous-safe functions within signal handlers. See here.
You could place the above in a C/Objective-C file and use it in Swift via a Bridging Header. Call setHandler() somewhere in the beginning of your application's lifecycle, e.g. in applicationDidFinishLaunching, and you should now have a chance to do some work before your app is Force Quit. I don't know how much time you get here, so I'd keep the workload as light as possible (avoid starting mission-critical stuff here, I guess?).
Here's some background info:
In a typical Quit
The Quit procedure is actually a part of Apple Events.
If the application is NSDocument-based, the behavior depends on the saving parameter, which has one of these three values:
NSSaveOptionsNo: The application quits without sending a close message to any document.
NSSaveOptionsYes: Each unmodified document is sent a close message; each modified document is sent the following message:
saveDocumentWithDelegate:didSaveSelector:contextInfo:
NSSaveOptionsAsk: (This is the default value if no saving parameter is supplied in the event.) If there are modified documents
open, the NSDocumentController sends itself this message:
reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo:
If the application is not NSDocument-based, the application delegate is sent this message (if it is implemented):
applicationShouldTerminate:
You can modify the default behavior by implementing this method.
Source: How Cocoa Applications Handle Apple Events
During Force Quit
The application is sent a SIGTERM which can be caught and dealt with by your application. Ideally, the application would clean up and exit as gracefully as possible, but this isn't required, and the signal can even be ignored.
An impatient user (and I strongly suspect that Force Quit does this eventually) may send a SIGKILL, which cannot be ignored and totally goes over anything you as the developer can stop.
Extra Information and Resources:
What does Force Quit do in OS X?
What signals does OS X send for the Quit and Force Quit commands?
How Cocoa Applications Handle Apple Events
SIGTERM vs. SIGKILL - major.io
C Signal Handling - Wikipedia
I have a Scala Play application and one of the controllers fires a Future which does some logging. I have a simple call back function which executes when the Future completes.
I have written a test to check whether this logging happens. The rough logic is as follows:
feature{
scenario{
Given()
// set up the call
When()
// make a FakeRequest via reverse routing - logging will done in a separate thread via a Future
Then()
Thread.sleep(50) // sleep to allow logging to finish
// check if the logging has been done
The issue is the Thread.sleep. I have added that call in to block the main testing thread in order to give enough time to elapse for the Future which does the logging in a separate thread to complete before actually doing the checks to see if the logging has been done.
My question is whether there is a better way to do this? In reality if my application is running and the logging is taking an inordinate amount of time, then the main thread which governs the application will not terminate until the Future that does the logging in a separate thread finishes. So I don't see a problem of putting in the Thread call above to simulate that. But I just want to confirm if this is correct.
For me, there is absolutely no other way than to do this. If I try to replicate how the app behaves in reality with my test, then the main thread for the test should complete and terminate even though the future for the logging is still going on; there is no call back in the test and neither should there be.
Assuming you're using ScalaTest ; you can use whenReady construct ; which periodically inspects the passed future, until it is either ready or the configured timeout has been surpassed;
see
http://www.artima.com/docs-scalatest-2.0.M5/org/scalatest/concurrent/Futures.html
http://doc.scalatest.org/2.0/index.html#org.scalatest.concurrent.ScalaFutures
I'm trying to port a C console program over to iPhone. I have imported all the code into my project, and I'm calling it's main() in an NSOperation when the user clicks a button on the UI.
Anyway, this program is complicated and creates many of its own threads. The program calls "exit()" many times as well- this would crash the entire iPhone app, but I really want the user to be able to restart the C program if it does it.
I've been working on cleaning up these exit conditions, and I've used pthread_exit() in some of the child threads the C program creates. However, when I call pthread_exit() in the thread that is created from the NSOperation object, the app's main thread get's a SIGABRT signal and the entire app crashes.
Am I correctly assessing the situation? I am new to iOS programming so this signal may be coming from elsewhere... And if I am correct, what is the best way to get around this?
(Oh, and about using "return 0" to exit this NSOperation thread: the condition I want to exit from is nested deep in C program functions, I want to avoid changing as much structure of the program as possible, since it already very complicated)
Thanks in advance for any help!
NSOperationQueue executes it’s operations on GCD queues. While those execute their jobs on pthreads those threads are private to GCD and you are not allowed to modify or exit them using pthread APIs. There is documentation on Compatibility with POSIX Threads, which explicitly states which pthread functions are allowed and which not.
To solve your problem you probably should not let your pthread code run on a NSOperationQueue but on a new POSIX thread you create just for that.
don't kill your pthreads -- let them exit naturally. as well, exit != pthread_exit. the author was clearly not considering cleanup when calling exit. so you are really just swallowing fatal errors by killing the threads.
it would be a miracle if it were incapable of resulting in undefined behaviour, or other nasty things like leaks or deadlocks.
in short, the library is being misused. you should handle the errors gracefully if you intend to continue execution. that can require a lot of work.
My iPhone application supports a proprietary network protocol using the CocoaAsyncSocket library. I need to be able to send a network message out when my iPhone application is closed. The code that sends the message is getting called from the app delegate, but the application shuts down before the message actually goes out. Is there a way to keep the application alive long enough for the message to go out?
Bruce
The docs from Apple don't specifically state this, but the sense I get from looking around the Web and from personal experience is that you have about 4 to 5 seconds after the user hits the Home button to shut your app before your application actually terminates. The iPhone OS is controlling this so you can't block the termination to allow your program to finish first. Basically when your time is up, your program is killed.
There may be another solution, though. First I'd confirm that your code is really taking more than 5 seconds to run. Perhaps you can have it run in response to a button tap, and time how long it runs. If it is more than 5 seconds, you probably are running into this time out issue.
You might then find a way to trigger a message to be sent from a server that is always running. You should have enough time to trigger a remote action, which in turn could then take as long as it needs to run.
Or perhaps you could save the vital information to the iPhone file system on exit, and send that message the next time someone starts the application, which should theoretically give you enough time.
Hope this helps!
I assume you're already calling it from your AppDelegate's:
- (void)applicationWillTerminate:(UIApplication *)application
But as you've discovered there's no guarantee it'll be called or will be allowed to finish. There are a few options that may or may not work depending on what you're trying to do:
If you need the server to perform some sort of cleaning operation triggered by when the client app is gone then you could try watching for TCP socket closure on the server and treating that as the triggering event. But if you explicitly need to send data back with the closure this may not work.
If the data you're sending back is not time-sensitive then you can do like most of the analytics libraries do and cache the data (along with a uuid) on the client then try to send it on app closure. If it goes through, you can clear the cache (or do it the next time the app is run). If it doesn't, it's saved and you can send out when the app is run next. On the server, you would use the uuid to avoid duplicate requests.
If the material is time-sensitive then your best bet is to implement heartbeat and send periodic updated values to the server. Then when the client app dies the server times out the heartbeat and can use the last received value as the final closing point of data.
In either case, if an explicit closure event is required by your custom protocol then you may want to reconsider using it in a real-life mobile environment where things have to be much more fluid and tolerant of failure.
As others have noted, there's no way to be absolutely certain that you'll be able to send this, but there are approaches to help.
As Ken notes, you do in practice get a few seconds between "willTerminate" and forced termination, so there generally is time to do what you need.
A problem you're almost certainly running into is with CocoaAsyncSocket. When you get the "willTerminate" message, you're on the last run loop of the main thread. So if you block the main thread, and CocoaAsyncSocket is running on the main thread, it'll never get processed. As I recall, CocoaAsyncSocket won't actually send all the data until the next event loop.
One approach, therefore, is to keep pumping the event loop yourself:
- (void)applicationWillTerminate:(UIApplication *)application
{
// ...Send your message with CocoaAsyncSocket...
while (! ...test to see if it sent...)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
}
I've also looked at putting this work onto a background thread and letting the main thread terminate, in theory letting us go back to Springboard while continuing to run for a few seconds. It's not immediately clear to me whether this will work properly using NSThread (which are detached). Using POSIX threads (which are joinable by default) may work, but probably circumvents any advantages of the background thread. Anyway, it's something to look at if useful. In my apps, we've used the "post next time we launch" approach, since that always works (even if you crash).
I am trying to post some data before my application terminates. Iam doing this by genrateing sockets using CFStreamCreatePairWithSocketToCFHost and later on I have the callbacks for reading and writing.
But I am not able to post any data. It goes through all the functions but doesnot enter into callbacks. Does that make sense to anyone?. Is there anyway to get this working?
Thanks,
Sowri
Yes, after applicationWillTerminate is called, there are no more iterations of the run loop. Since CFSocket and CFStream both use the run loop to manage the sockets and to provide data via the callback, this will not work. Also, it's very important to note that the application may be restricted from doing certain things at this stage and that if your application does not terminate, the operating system will terminate the application. It may be a better idea to write a small log to a database and then post that information back the next time the application starts.
My gut feeling is that after the applicationWillTerminate method is done, it will just stop the whole app, without giving any other run loop the chance to execute, let alone do callbacks. So my guess is that calling asynchronous methods in the applicationWillTerminate won't even start. You're just too late at that point to start networking.
The applicationWillTerminate: callback is not the place to do any kind of critical operation because as the name implies, your application will terminate and it won't wait for your code to finish doing something.
What are you trying to post; if you explain why you want to do this we may be able to offer a better solution.