Well... – apparently, nothing! If I try
Prelude Control.Concurrent.Async Data.List> do {_ <- async $ return $! foldl'(+) 0 [0,0.1 .. 1e+8 :: Double]; print "Async is lost!"}
"Async is lost!"
one processor core starts going wild for a while, the interface stays as normal. Evidently the thread is started and simply runs as long as there is something to do.
But (efficiency aside), is that in principle ok, or must Asyncs always be either cancelled or waited for? Does something break because there just isn't a way to read the result anymore? And does the GC properly clean up everything? Will perhaps the thread in fact be stopped, and that just doesn't happen yet when I try it (for lack of memory pressure)? Does the thread even properly "end" at all, simply when the forkIOed action comes to an end?
I'm quite uncertain about this concurrency stuff. Perhaps I'm still thinking too much in a C++ way about this. RAII / deterministic garbage collection certainly make you feel a bit better cared for in such regards...
Internally, an Async is just a Haskell thread that writes to an STM TMVar when finished. A cancel is just sending the Haskell thread a kill signal. In Haskell, you don't need to explcititly kill threads. If the Async itself can be garbage collected, then the thread will still run to its end, and then everything will be properly cleaned up. However, if the Async ends in an exception, then wait will propagate the exception to the waiting thread. If you don't wait, you'll never know that the exception happened.
Related
I have a program that uses multiple threads to brute force the decryption of some encrypted string. The main thread has a channel, and the sender is cloned and sent to each thread. When a thread finds an answer, it sends it to the receiver which is in the main thread.
In this program I am not joining the threads, instead I use the blocking call sender.recv() to suspend the main thread until a single other thread finishes.
My hope is, once this call finishes, the main thread will return and all the other worker threads will be terminated.
Is this a poor design choice? Are there drawbacks of not having some condition in the other threads which would cause them to return when the solution has been discovered? Is it okay/safe to rely on the compiler to clean up my threads before they've technically finished?
Assuming there's no cleanup to be done, what you've done is mostly harmless. I'm assuming your worker thread looks something like this right now.
fn my_thread() {
// ... lots of hard work ...
channel.send(my_result);
}
and if that's the case, then "I received the result" and "the other thread is terminated" are very similar events, and the difference of "this function returned" is probably irrelevant. But suppose someone comes along and changes the code to look like this.
fn my_thread() {
// ... lots of hard work ...
channel.send(my_result);
do_cleanup_stuff();
}
Now do_cleanup_stuff() might not get a chance to run, if your main thread terminates before my_thread does. If that cleanup function is important, that could cause problems. And it could be more subtle than that. If any local variable in my_thread holds a file handle or an open TCP stream or any other object with a nontrivial Drop implementation, that value may not get a chance to Drop properly if you don't join the thread.
So it's probably best practice to join everything, even if it's just a final step at the end of your main.
I wrote a test program in Haskell on the Raspberry Pi that plays a delightful tune
on a buzzer connected to a GPIO pin.
Here are the imports I used:
import qualified Control.Concurrent as C
import qualified Control.Monad as M
import System.IO
import qualified System.Posix.Unistd as P
Here are the functions that toggle the pin by writing to
the /sys/class/gpio/gpio16/value file:
changePin2 :: Handle -> String -> Int -> IO ()
changePin2 handle onOff delay = do
pos <- hGetPosn handle
hPutStr handle (onOff ++ "\n")
hFlush handle
hSetPosn pos
P.usleep delay
--C.threadDelay delay
blinkOn2 :: Handle -> Int -> IO ()
blinkOn2 handle delay = do
changePin2 handle "1" delay
changePin2 handle "0" delay
finally, here is an example of playing one note with a pause before the next one:
mapM_ (blinkOn2 h) (replicate 26 1908)
P.usleep 50000
-- C.threadDelay 50000
When I first tried it, I used threadDelay and it sounded terrible. It was low pitched,
suggesting the delay was longer than expected and all notes sounded more or less the same.
Using the usleep function improved things considerably.
Finally, adding the -threaded option when compiling with ghc made the sound even cleaner.
ghc -threaded buzzer1t.hs
I do not understand why either of these improved it and if anyone knows it would help greatly.
googling seems to reveal that usleep and friends are delays at the OS level whereas threadDelay
only pertains to the thread in the Haskell program itself. threadDelay also seems like the
more recommended one and considered better practice even though in this case usleep is clearly
superior.
I think the documentation is a good start here:
GHC Note: threadDelay is a better choice. Without the -threaded option, usleep will block all other user threads. Even with the -threaded option, usleep requires a full OS thread to itself. threadDelay has neither of these shortcomings.
To expand a bit further: The GHC runtime multiplexes user threads over system threads. The default runtime uses only a single OS thread, regardless of how many user threads there are. Most blocking calls to external code are written such that they deschedule the current Haskell user thread while they're in external code, which is allowed to execute concurrently with Haskell code. This means that even the default runtime with a single OS thread can handle multiple user threads doing IO simultaneously, for instance.
In this world, actually blocking the OS thread is considered a somewhat hostile activity. threadDelay just marks the current thread as not runnable until the specified amount of time has expired. This is much friendlier with the runtime system, as it releases the underlying OS thread.
When you use the threaded runtime, you get multiple OS threads to execute user threads, but it's still somewhat hostile to grab one and not release it. Among other things, it prevents the garbage collector from running (it waits until it can pause all user threads at known safe points, so it doesn't corrupt memory in use concurrently), and OS threads are significantly more memory-heavy than user threads if you add extras to make up for lost concurrency.
So for most software, threadDelay is a much better citizen. But it has downsides. The thread doesn't necessarily resume immediately. It becomes available to be scheduled at the given time, but that doesn't mean it actually runs. That still depends on other threads yielding. That's almost certainly the cause of the trouble you were having - the additional delay waiting to go from runnable to actually running. usleep is around specifically for the cases when that gets in the way. Seems like a fine reason to use it when needed.
I have read that a forever process like daemon should run with a sleep() in their while(1) or for(;;) loop. They say, it is required because otherwise this process will always be in a run queue and the kernel will always run it. This will block the other process. I don't agree that it will block the other process completely. If there is a time slicing, then it will execute other process. But, certainly it will steal a time from others. Making a delay for other process since this process is always in the run state. By default, the Linux runs as a round-robin. The first task is swapd, then other tasks . This is a circular link list with first task as swapd(process-id is 0) and then other tasks. I believe this is still based as time sliced. A particular time for each process. These tasks are nothing but the process-descriptor. I believe this link list is maintained by the init process. Please do correct me here If I am wrong. Other question is if we need to give a sleep() then what should be its value? How can we determine the sleep value to get the best results?
If your program has useful things to do, don't throttle it. A program can move out of the run queue by doing blocking stuff like IO and waiting.
If you are writing a polling loop that can spin an arbitrary number of times you probably want to throttle it a bit with sleep because spinning too often has little value.
That said, polling loops are a means of last resort. Normally, programs perform useful work with every instruction, so they don't sleep at all.
Sleep is almost certainly the wrong solution.
Usually what you do it call a blocking function which wakes you up when there's something for you to do.
For example, if you're a network service you'd want to remain inactive until a request arrives.
In other words, the core of your daemon should not look like this:
while(1)
{
if (checkIfSomethingToDo())
doSomething();
else
sleep(1);
}
but rather a little like this:
while(1)
{
int ret = poll(fds, nfds, -1);
if (ret > 0)
doSomething();
}
Have the kernel put you to sleep until there's actual work to do. It's not hard to implement, you'd be a lot more efficient (not stealing CPU time from others, only to waste it doing no actual work) and your response latency will go down too.
A sleep forces the os to pass execution to another thread and therefore is helpfull, or at least fair. Start with sleep one. Should be ok.
I've got a program which uses several threads. As I understand it, when thread 0 exits, the entire program exits, regardless of any other threads which might still be running.
The thing is, these other threads may have files open. Naturally, this is wrapped in exception-handling code which cleanly closes the files in case of a problem. That also means that if I use killThread (which is implemented via throwTo), the file should also be closed before the thread exits.
My question is, if I just let thread 0 exit, without attempting to stop the other threads, will all the various file handles be closed nicely? Does any buffered output get flushed?
In short, can I just exit, or do I need to manually kill threads first?
You can use Control.Concurrent.MVar to achieve this. An MVar is essentially a flag which is either ''empty'' or "full". A thread can try to read an MVar and if it is empty it blocks the thread. Wherever you have a thread which performs file IO, create an MVar for it, and pass it that MVar as an argument. Put all the MVars you create into a list:
main = do
let mvars = sequence (replicate num_of_child_threads newEmptyMVar)
returnVals <- sequence (zipWith (\m f -> f m)
mvars
(list_of_child_threads :: [MVar -> IO a]))
Once a child thread has finished all file operations that you are worried about, write to the MVar. Instead of writing killThread you can do
mapM_ takeMVar mvars >> killThread
and where-ever your thread would exit otherwise, just take all the MVars.
See the documentation on GHC concurrency for more details.
From my testing, I have discovered a few things:
exitFailure and friends only work in thread 0. (The documentation actually says so, if you go to the trouble of reading it. These functions just throw exceptions, which are silently ignored in other threads.)
If an exception kills your thread, or your whole program, any open handles are not flushed. This is excruciatingly annoying when you're desperately trying to figure out exactly where your program crashed!
So it appears it if you want your stuff flushed before the program exits, then you have to implement this. Just letting thread 0 die doesn't flush stuff, doesn't throw any exception, just silently terminates all threads without running exception handlers.
I have this POSIX thread:
void subthread(void)
{
while(!quit_thread) {
// do something
...
// don't waste cpu cycles
if(!quit_thread) usleep(500);
}
// free resources
...
// tell main thread we're done
quit_thread = FALSE;
}
Now I want to terminate subthread() from my main thread. I've tried the following:
quit_thread = TRUE;
// wait until subthread() has cleaned its resources
while(quit_thread);
But it does not work! The while() clause does never exit although my subthread clearly sets quit_thread to FALSE after having freed its resources!
If I modify my shutdown code like this:
quit_thread = TRUE;
// wait until subthread() has cleaned its resources
while(quit_thread) usleep(10);
Then everything is working fine! Could someone explain to me why the first solution does not work and why the version with usleep(10) suddenly works? I know that this is not a pretty solution. I could use semaphores/signals for this but I'd like to learn something about multithreading, so I'd like to know why my first solution doesn't work.
Thanks!
Without a memory fence, there is no guarantee that values written in one thread will appear in another. Most of the pthread primitives introduce a barrier, as do several system calls such as usleep. Using a mutex around both the read and write introduces a barrier, and more generally prevents multi-byte values being visible in partially written state.
You also need to separate the idea of asking a thread to stop executing, and reporting that it has stopped, and appear to be using the same variable for both.
What's most likely to be happening is that your compiler is not aware that quit_thread can be changed by another thread (because C doesn't know about threads, at least at the time this question was asked). Because of that, it's optimising the while loop to an infinite loop.
In other words, it looks at this code:
quit_thread = TRUE;
while(quit_thread);
and thinks to itself, "Hah, nothing in that loop can ever change quit_thread to FALSE, so the coder obviously just meant to write while (TRUE);".
When you add the call to usleep, the compiler has another think about it and assumes that the function call may change the global, so it plays it safe and doesn't optimise it.
Normally you would mark the variable as volatile to stop the compiler from optimising it but, in this case, you should use the facilities provided by pthreads and join to the thread after setting the flag to true (and don't have the sub-thread reset it, do that in the main thread after the join if it's necessary). The reason for that is that a join is likely to be more efficient than a continuous loop waiting for a variable change since the thread doing the join will most likely not be executed until the join needs to be done.
In your spinning solution, the joining thread will most likely continue to run and suck up CPU grunt.
In other words, do something like:
Main thread Child thread
------------------- -------------------
fStop = false
start Child Initialise
Do some other stuff while not fStop:
fStop = true Do what you have to do
Finish up and exit
join to Child
Do yet more stuff
And, as an aside, you should technically protect shared variables with mutexes but this is one of the few cases where it's okay, one-way communication where half-changed values of a variable don't matter (false/not-false).
The reason you normally mutex-protect a variable is to stop one thread seeing it in a half-changed state. Let's say you have a two-byte integer for a count of some objects, and it's set to 0x00ff (255).
Let's further say that thread A tries to increment that count but it's not an atomic operation. It changes the top byte to 0x01 but, before it gets a chance to change the bottom byte to 0x00, thread B swoops in and reads it as 0x01ff.
Now that's not going to be very good if thread B want to do something with the last element counted by that value. It should be looking at 0x0100 but will instead try to look at 0x01ff, the effect of which will be wrong, if not catastrophic.
If the count variable were protected by a mutex, thread B wouldn't be looking at it until thread A had finished updating it, hence no problem would occur.
The reason that doesn't matter with one-way booleans is because any half state will also be considered as true or false so, if thread A was halfway between turning 0x0000 into 0x0001 (just the top byte), thread B would still see that as 0x0000 (false) and keep going (until thread A finishes its update next time around).
And if thread A was turning the boolean into 0xffff, the half state of 0xff00 would still be considered true by thread B so it would do its thing before thread A had finished updating the boolean.
Neither of those two possibilities is bad simply because, in both, thread A is in the process of changing the boolean and it will finish eventually. Whether thread B detects it a tiny bit earlier or a tiny bit later doesn't really matter.
The while(quite_thread); is using the value quit_thread was set to on the line before it. Calling a function (usleep) induces the compiler to reload the value on each test.
In any case, this is the wrong way to wait for a thread to complete. Use pthread_join instead.
You're "learning" multhithreading the wrong way. The right way is to learn to use mutexes and condition variables; any other solution will fail under some circumstances.