how to resume/suspend a pthread in iphone os? - iphone

Now i face a problem in my porting job, when i need to implement a thread class that will work in not only wince, symbian ,but also unix-like system, like iphone.
I own a suspend/resume interface to implement, anything is ok in wince/symbian except iphone, i use the posix pthread to finish my job, but i search the whole docsets for a resume/suspend-like interface. Things seem to be difficult, pthread in iphone own a pthread_create_suspended_np that can create a thread in a suspend mode. Now how can i resume or suspend a thread after the thread has run to its stuff in anytime.
BTW, i search Google for some help, it seems that someone else also have this problem .
Some guys suggest use the SIGHUP signal, but this will suspend the whole process, that's absolutely not ok .
Many thanks if you guys can tell me some solutions for this problem.

It's actually a bad idea to try and control threads externally. You never know what state they may be in when you suspend them. If they have a mutex lock on a resource that's needed elsewhere, you can easily end up with a deadlock situation.
We had to create a "safe" suspend functionality without resorting to any non-portable pthread extensions a while ago and I'll try to remember how we did it.
It consisted of a suspension mutex for each thread and a variable indicating that threads state. So the thread we wanted to suspend would have a loop (they mostly do) that went something like this:
while true:
set mystate = suspended
claim mymutex
yield
release mymutex
set mystate = running
do some work
and the code to suspend/resume the thread would be:
function suspend (state,mutex):
claim mutex
while state <> suspended:
yield
function resume (state,mutex):
release mutex
while state <> running:
yield
What the suspender would do is basically get a lock on the mutex and wait for the thread to enter suspended state (the writing to mystate was done only by the suspendee and did not have to be protected by another mutex). The suspend function did not return until it was guaranteed that the suspendee would be stopped.
Similarly, resuming the thread released the mutex so the suspendee could restart and then waited until it had restarted before returning.
This allowed suspension to take place but under the control of the thread being suspended. That was much safer since it could ensure it could only be suspended at safe points when it didn't have any locks that could deadlock the application.

To suspend and resume a running thread, I believe you need to use pthread_cond_wait. Basically, that suspends the calling thread until the condition variable becomes true. Of course, you need to also give each thread a way to figure out when to call the function.

you give me a clue to solve this problem , yet this method or pthread_cond_wait just wait/singal when design some kind of situation. How can i suspend the special pthread without know more info. about the thread, we just own a thread id, we suspend it in another thread, when we wanna resume the suspended thread, we just probably run the resume function in anywhere. can we do something like this? or any other idea ?
regards.

Related

Is it sensible to start `CLLocationManager` on a background thread?

According to the documentation of CLLocationManagerDelegate
The methods of your delegate object are called from the thread in which you started the corresponding location services. That thread must itself have an active run loop, like the one found in your application’s main thread.
I am not clear as to whether this means that to receive location manager updates on a background thread, we must instantiate the location manager on that background thread or simply call the startUpdatingLocation() method on that thread.
In any event, this explains an issue when a CLLocationManagerDelegate does not receive any events from a CLLocationManager which was started on a background thread:
That thread must itself have an active run loop
If I understand run loop functioning correctly, all NSThreads are instantiated with a run loop, but the run loop will only be running if you assign some work to the thread. Therefore, to have a CLLocationManager send events correctly on a background thread, we need to set the thread's run loop to loop permanently so that it can process the CLLocationManager's calls as they arrive.
A reasonable solution to making sure the run loop is running is suggested in this question but the author implies that this is a processor expensive way of doing it.
Also, according to the threading documentation,
Threading has a real cost to your program (and the system) in terms of memory use and performance
I appreciate that we are all using lots of threading anyway, by using Grand Central Dispatch, but Grand Central Dispatch probably mitigates a lot of this in its internal thread management.
So my first question is, is it worthwhile setting up a background thread with a continuously running run loop, in order to have location events dealt with on a background thread, or will this involve an unreasonable extra amount of processing when compared to leaving the manager on the main thread?
Secondly, if it is worthwhile, is there a good way to do this using Grand Central Dispatch. As I understand the documentation, Grand Central Dispatch manages its own threads and we have no means of knowing which thread a given block will be executed on. I presume we could simply execute the usual run loop code to make the run loop of whichever thread our CLLocationManager instantiation is run on loop continuously, but might this not then affect other tasks independently assigned to Grand Central Dispatch?
This is a somewhat opinion-based question, but I have a pretty strong opinion on it :D
No.
Just deliver the events to the main queue, and dispatch any work to a background queue if it's non-trivial. Anything else is a lot of complexity for little benefit. CLLocationManager pre-dates GCD, so this was useful information in the days when we occasionally managed run loops by hand and dispatching from one thread to another was a pain. GCD gets rid of most of that, and is absolutely the tool you should use for this. Just let GCD handle it with dispatch_async.
You absolutely should not set up your own NSThread for this kind of thing. They're still necessary at times for interacting with C++, but generally if GCD can handle something, you should let it, and avoid NSThread as much as possible.

How can one thread determine if a different thread has crashed?

I have a background thread that is doing a bunch of work - loading the application. The main thread is displaying progress on a UIProgressView.
The background thread is being spawned with performSelectorInBackground (though, I'm not wed to this method if a different approach makes this problem easier to solve)
[self performSelectorInBackground:#selector(loadAppInBackground) withObject:self];
On a couple occasions a bug has caused the background thread to crash (different bugs as the app evolves) which results in the progress bar stopping, but the user getting no clear indication that anything is wrong.
I'd like to detect this situation and fail more gracefully than simply hanging until the user gives up on waiting.
Because the duration of the load process can vary greatly, simply timing out isn't an ideal option.
What's the best way for the foreground thread to detect that the background thread has failed? Since the foreground thread is busy dealing with the UI, would it require a second background thread to monitor the first? That seems ugly.
Is there some thread-to-thread communication mechanism that could be used to "ping" the background process? Better yet, a low level system mechanism of checking the status of other threads?
The debugger knows about all the threads that are running... and seems to know their status. I'm wondering if there's a call available to my app to do the same.
If the background task runs in some sort of regular cycle (eg, there's a big loop where much of the work gets done), it can set a flag every so often to indicate that it's still alive.
One way to do this is to have background thread store [NSDate timeIntervalSinceReferenceDate] somewhere, and, in your main thread, occasionally (perhaps on a timer) compare that to the current time. If the difference is greater than some reasonable limit you can guess that the background thread has died.
Another way is to have the background thread simply set a Boolean, and have the main thread interrogate that and clear it on some regular basis. If the Boolean doesn't get set again between main thread interrogations you can infer that it has died.
The first technique has the advantage that you can "tune" the "reasonable limit" to tolerate code (in either thread) that is somewhat irregular in it's timing. The second approach generally requires timings that are more predictable.
Of course with either approach you want to somehow avoid "blowing the whistle" if the background thread has just finished up and you simply haven't recognized that yet.
A common technique is to have an extra thread to check for life signs of the thread in question - a so called heartbeat thread. The heartbeat thread polls the thread by checking if it responds in a timely manner, if not, deems the thread dead and terminates it.
A simple heartbeat thread implementation would be to check a counter that is incremented regularly by the other thread, if the counter is not incremented within a certain time it is regarded as dead and then an appropriate action could be taken like restarting thread or killing app. Another more common way is if the hb thread sends messages to the thread and checks for a response with a timeout.
It seems like there is no mechanism in objective c to check the status of a background thread directly. Any of the answers provided are decent options... either timing out, or having the thread create some sort of evidence of its continued existence.
I was hoping for something a little more simple, reliable, and real-time.
I'm going to experiment with catching an exception in the thread and perhaps producing a notification like "BackgroundThreadException" that the foreground thread could listen for and react to.

iOS - Porting a C program: Calling pthread_exit() in an NSOperation job

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.

Do I have an option to access all threads running in my app?

I have used detachNewThreadSelector method to create threads in my app. At some point of time, when user is logged out from the app, I should kill all running threads in the app. How can I achieve it?
If you create a thread with detachNewThreadSelector you pretty much have to let it finish by itself :(
A better option if you want to be able to control background tasks would be NSOperationQueue - with this you can pass cancel messages to operations.
(Apple docs here)
EDIT : If you don't want to use NSNotificationCenter, you could set a flag that your background threads periodically check and if it's set they will exit themselves. However, you would have to be careful about thread safety there :)
Use "normal" NSThread constructor - (id)initWithTarget:... and save your thread object.
Or save thread objects somewhere after thread start.
Don't save thread objects at all, just use some separate flags that you'll check in your threads and exit them.

Killing a thread or an alternative

Is there any way I can kill a thread spawn through:
[NSThread detachNewThreadSelector:#selector(serverFetchInThread) toTarget:self withObject:nil];
The scenario I am working on is that in my main thread I am letting user enter data in my search bar and what ever user is typing I need to send to server for searching in a separate thread. Now, if user changes his selection by deleting old data and entering new data I do not want the previous thread to waste its time, kill it and spawn a new thread with new data.
Be there any other better way to handle this situation, please guide me.
No, there is no way to kill a thread from another thread. And for good reason as there is no way to do so in a fashion where the targeted thread is killed without risk of crashing the app.
To directly answer your question; you need to have some kind of a flag that indicates to the thread that it should stop doing whatever it is doing and exit.
However, a couple of questions are raised by your question:
First, why are you using threads and not using GCD? Concurrency via GCD or NSOperation is the generally recommended way to solve such problems.
Secondly, if you are talking to a server, are you using HTTP (most of the time, that is the case)? If so, why not directly use the asynchronous features of NSURL and friends?
Have a good look at using NSOperationQueue.
You can subclass NSOperation it to wrap up your server communications, and even make that queue serial (maximum operations = 1).
If a server operation is not yet finished and user has generated more input, you can cancel the existing one, and add the new one.
Due to the effect of the NSOperation wrapping your connection, you can just use the simple synchronous version and keep the connection handling very straightforward.
Also worth mentioning is compatibility. I would prefer to use GCD and blocks, but for compatibility, NSOperationQueue is required.