How can one know if a pthread died?
Is there a way to check a pthreads status?
if(pthread_kill(the_thread, 0) == 0)
{
/* still running */
}
See: pthread_kill
Note: there is an inherent risk to using pthread_kill() to test if a
thread is still running. See this post for an explanation:
How do I determine if a pthread is alive?
If you don't need to write a portable application and can use GNU extensions, you can use pthread_tryjoin_np. I believe there isn't another way to do it, except for setting up communication between two threads (e.g. using a global mutex which is hold by a thread as long as it is alive).
I want to add to the discussion the fact that a thread can just die in another case that is not mentioned here in the case of a signal such as SIGPIPE when it is not handled by the hosting process or the thread it self and in situations when such a signal can arise
Related
First off, I'd like to clarify that I'm not talking about concurrency here. I fully understand that having multiple threads modify the UI at the same time is bad, can give race conditions, deadlocks, bugs etc, but that's separate to my question.
I'd like to know why MacOS/iOS forces the main thread (ID 0, first thread, whatever) to be the thread on which the GUI must be used/updated/created on.
see here, related:
on OSX/iOS the GUI must always be updated from the main thread, end of story.
I understand that you only ever want a single thread doing the acutal updating of the GUI, but why does that thread have to be ID 0?
(this is background info, TLDR below)
In my case, I'm making a rust app that uses a couple of threads to do things:
engine - does processing and calculations
ui - self explanatory
program/main - monitors other threads and generally synchronizes things
I'm currently doing something semi-unsafe and creating the UI on it's own thread, which works since I'm on windows, but the API is explicitly marked as BAD to use, and it's not cross compatible for MacOS/iOS for obvious reasons (and I want it to be as compatible as possible).
With the UI/engine threads (there may be more in the future), they are semi-unstable and could crash/exit early, outside of my control (external code). This has happened before, and so I want to have a graceful shutdown if anything goes wrong, hence the 'main' thread monitoring (among other things it does).
I am aware that I could just make Thread 0 the UI thread and move the program to another thread, but the app will immediately quit when the main thread quits, which means if the UI crashes the whole things just aborts (and I don't want this). Essentially, I need my main function on the main thread, since I know it won't suddenly exit and abort the whole app abruptly.
TL;DR
Overall, I'd like to know three things
Why does MacOS/iOS enforce the GUI being on THread 0 (ignoring thread-safety outlined above)
Are there any ways to bypass this (use a different thread for GUI), or will I simply need to sacrifice those platforms (and possible others I'm unaware of)?
Would it be possible to do something like have the UI run as a separate process, and have it share some memory/communicate with the main process, using safe, simple rust?
p.s. I'm aware of this question, it's relevant but doesn't really answer my questions.
Why does MacOS/iOS enforce the GUI being on Thread 0.
Because it's been that way for over 30 years now (since NeXTSTEP), and changing it would break just about every program out there, since almost every Cocoa app assumes this, and relies on it regularly, not just for the main thread, but also the main runloop, the main dispatch group, and now the main actor. External UI events (which come from other processes like the window manager) are delivered on thread 0. NSDistributedNotifications are delivered on thread 0. Signal handling, the list goes on. Yes, it is certainly possible for Darwin (which underlies Cocoa) to be rewritten to allow this. That's not going to happen. I'm not sure what other answer you want.
Would it be possible to do something like have the UI run as a separate process, and have it share some memory/communicate with the main process, using safe, simple rust?
Absolutely. See XPC, which is explicitly for this purpose (communicating, not sharing memory; don't share memory, that's a mess). See sys-xpc for the Rust interface.
I am trying to write a customized threadpool suited to my purpose using pthreads, and I am new to pthreads. I read these (POSIX threads programming and Linux Tutorial Posix Threads) tutorials online and they were quite helpful, but i still have some (maybe silly) doubts regarding mutexes and condition variables:
What is the scope of a mutex? Will a global mutex lock all the global variables so that only one thread can access them at a time? If i have two global mutexes, would they lock the same set of variables? What about a mutex that is declared inside a class or a function, what will happen when i lock/unlock it?
If i just plan to just read a global variable, and not modify it at all, should i still use a mutex lock?
If i am correct, a condition variable is used to wake up other threads which are sleeping (or blocked using pthread_cond_wait()) on some condition. The wake up call to sleeping threads is given by pthread_cond_signal() or pthread_cond_broadcast() from some other thread. How is the flow of control supposed to occur so that some all or one thread wake(s) up to do a work and wait until next work is available? I am particularly interested in a scenario with 4 threads.
Is there a way to set the affinity of a thread to a particular processor core before it is created (so that it starts execution on the desired core and no shifting of cores occur after creation)?
I am sorry if the questions look silly, but as i said, i am new to this. Any help, comments, code or pointer to good resources is appreciated. thanks in advance for your help.
That's a lot of questions. A few answers.
(1a) The scope of a mutex is whatever you program it to be. In that sense it is no different from any other kind of variable.
(1b) A global mutex will protect whatever variables you program it to protect. I think from your other questions you might have a fundamental misunderstanding here. There is nothing magical about mutexes. You can't just declare one and say "Ok, protect these variables", you have to incorporate the mutex in your code. So if you have two functions that use variable X and one does a mutex lock/unlock around any changes to the variable and the other function completely ignores that a mutex even exists you really aren't protecting anything. The best example I can think of is advisory file locks - one program can use them but if another doesn't then that file isn't locked.
(1c) As a rule, don't have multiple mutexes locking the same data. It is an invitation to problems. Again the use of mutexes depends on programmed cooperation. If function A is protecting data B with mutex C while function D is protecting data B with mutex E then data B isn't protected at all. Function A can hold the lock on mutex C but since function D pays no attention to it it will just overwrite data B anyway.
(1d) Basic scoping rules apply.
(2) No. If the variable isn't going to change in any way that would make it inconsistent among threads then you don't need to lock it.
(3) There are a number of detailed answers on this on SO that go into considerable detail on this. Search around a bit.
(4) Not that I am aware.
Here's the situation, I have a thread running that is partially controlled by code that I don't own. I started the thread so I have it's thread id but then I passed it off to some other code. I need to be able to tell if that other code has currently caused the thread to block from another thread that I am in control of. Is there are way to do this in pthreads? I think I'm looking for something equivalent to the getState() method in Java's Thread class (http://download.oracle.com/javase/6/docs/api/java/lang/Thread.html#getState() ).
--------------Edit-----------------
It's ok if the solution is platform dependent. I've already found a solution for linux using the /proc file system.
You could write wrappers for some of the pthreads functions, which would simply update some state information before/after calling the original functions. That would allow you to keep track of which threads are running, when they're acquiring or holding mutexes (and which ones), when they're waiting on which condition variables, and so on.
Of course, this only tells you when they're blocked on pthreads synchronization objects -- it won't tell you when they're blocking on something else.
Before you hand the thread off to some other code, set a flag protected by a mutex. When the thread returns from the code you don't control, clear the flag protected by the mutex. You can then check, from wherever you need to, whether the thread is in the code you don't control.
From outside the code, there is no distinction between blocked and not-blocked. If you literally checked the state of the thread, you would get nonsensical results.
For example, consider two library implementations.
A: We do all the work in the calling thread.
B: We dispatch a worker thread to do the work. The calling thread blocks until the worker is done.
In both cases A and B the code you don't control is equally making forward progress. Your 'getstate' idea would provide different results. So it's not what you want.
I'm working on a project and cannot find any documentation that verifies signal/thread behavior for the following case.
I need to ensure that signals generated in a thread will be delivered by the offending thread (namely, SIGSEGV). I've been told that POSIX doesn't ensure this behavior and that pthreads, for example, can generate signals in pthread 1 yet have the signal delivered in pthread 2. Therefore, I'm planning on using clone(2) to have finer control of signal/thread behavior, but still cannot find documentation in the man pages that ensures signals will be delivered by the offending thread.
Hardcore systems programmers: any documentation or insights would be very much appreciated!
The POSIX chapter on Signal Generation and Delivery states that:
At the time of generation, a
determination shall be made whether
the signal has been generated for the
process or for a specific thread
within the process. Signals which are
generated by some action attributable
to a particular thread, such as a
hardware fault, shall be generated for
the thread that caused the signal to
be generated. Signals that are
generated in association with a
process ID or process group ID or an
asynchronous event, such as terminal
activity, shall be generated for the
process.
A synchronous SIGSEGV caused by an incorrect memory access in a thread is clearly such a signal "...generated by some action attributable to a particular thread...", so they are guaranteed to be generated for the offending thread (which means handled or ignored by that thread, as appropriate).
I'm pretty sure this works, even if it isn't guaranteed. I base this observation on the fact that I used to work at a company where we routinely handled SIGSEGV in multithreaded programs and printed a stack trace to a log file (based on currently location). We did this on a variety of platforms--windows, linux, tru64 unix, aix, hpux, sunos ... and maybe one or two others that I can't recall. This (usually!) works because the location of SIGSEGV is still on the current stack (the signal handling mechanism just adds a few call frames over top of it).
It's only fair to mention that there's very little that you should do in a signal handler because there aren't many functions that are async signal safe. We ignored this and mostly got away with it, except if I recall on sunos (or aix) where we would get burned--the process would occasionally (and seemingly randomly) hard exit inside the signal handler.
I believe the recommended approach is to NOT handle SIGSEGV, and let the process exit with a core dump so you can analyze later in a debugger.
When does one use pthread_cancel and not pthread_kill?
I would use neither of those two but that's just personal preference.
Of the two, pthread_cancel is the safest for terminating a thread since the thread is only supposed to be affected when it has set its cancelability state to true using pthread_setcancelstate().
In other words, it shouldn't disappear while holding resources in a way that might cause deadlock. The pthread_kill() call sends a signal to the specific thread, and this is a way to affect a thread asynchronously for reasons other than cancelling it.
Most of my threads tends to be in loops doing work anyway and periodically checking flags to see if they should exit. That's mostly because I was raised in a world when pthread_kill() was dangerous and pthread_cancel() didn't exist.
I subscribe to the theory that each thread should totally control its own resources, including its execution lifetime. I've always found that to be the best way to avoid deadlock. To that end, I simply use mutexes for communication between threads (I've rarely found a need for true asynchronous communication) and a flag variable for termination.
You can not "kill" a thread with pthread_kill(). If you try to send SIGTERM or SIGKILL to a thread with pthread_kill(), it will terminate the entire process.
I subscribe to the theory that the PROGRAMMER and not the THREAD (nor the API designers) should totally control its own software in all aspects, including which threads cancel which.
I once worked in a firm where we developed a server that used a pool of worker threads and one special master thread that had the responsibility to create, suspend, resume and terminate the worker threads at any time it wanted. Of course the threads used some sort of synchronization, but it was of our design and not some API-enforced dogmas. The system worked very well and efficiently!
This was under Windows. Then I tried to port it for Linux and I stumbled at the pthreads' stupid "theories" about how wrong it is to suspend another thread etc. So I had to abandon pthreads and directly use the native Linux system calls (clone()) to implement the threads for our server.