Do goroutines keep running even if main function is terminated? - multithreading

I am running a server where main fires off several go routines. like this:
main() {
go someFn(){
// will run for infinite time()
}
go otherFn()
}
I have two doubts:
what if the main function is exited? will these threads will still run or will terminate with the main function?
if no, then what is the best method to make the main function run forever/ or run till I need it? currently, I am using select{} command for making it run forever! is there any better and more efficient method available than select{}

I would recommend to read the language specification in its entirety — Go is one of a very small number of laguages whose language spec can really be read over two lunches (or a single one — if this is your, I dunno, third of fourth programming language).
To cite it:
Program execution begins by initializing the main package and then invoking the function main. When that function invocation returns, the program exits. It does not wait for other (non-main) goroutines to complete.
I would add that logically making main wait all non-main goroutines would be a bad thing for two reasons:
That would easily create situations where you could wait for a program to shut down for some indeterminate amount of time even if you do not want that (and you not always want that).
Logically, that would require inventing a "special" way to end main — something like abort(3) from C, and having such a way is a sure path for it to be abused.
Any sensible usage of goroutines where you actually need to wait on them anyway requires explicit synchronisation — just per the language specification and its memory model.
That is, when you want to wait on outstanding goroutines, you must do that explicitly.

The program exits when the function main() returns.
If one of someFn or otherFn runs forever, then call that function directly at the end of main. The main function never exits with this change.
If neither function runs forever, the use a sync.WaitGroup to wait on the goroutines and then exit.
The empty select statement select {} efficiently blocks a goroutine forever.

[Do] go routines keeps on running even if main function is terminated?
No.
This is asked once a week.

In my opinion, when it is difficult to remember a concept the best thing is to code such concept yourself.
Here is a simple program which demonstrates that go routines are terminated when main function exits:
package main
import (
"log"
"os"
"time"
)
func main() {
f, err := os.Create("./test.txt")
if err != nil {
log.Fatal("can not write to a file", err)
}
go func() {
for {
f.WriteString("new line created at: " + time.Now().String() + "\n")
time.Sleep(1 * time.Second)
}
}()
time.Sleep(5 * time.Second)
// writing to the file by goroutine will be finished in 5 seconds
// when main exits
}

Related

Are there any downsides to choosing not to join threads in Rust?

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.

Goroutines are cooperatively scheduled. Does that mean that goroutines that don't yield execution will cause goroutines to run one by one?

From: http://blog.nindalf.com/how-goroutines-work/
As the goroutines are scheduled cooperatively, a goroutine that loops continuously can starve other goroutines on the same thread.
Goroutines are cheap and do not cause the thread on which they are multiplexed to block if they are blocked on
network input
sleeping
channel operations or
blocking on primitives in the sync package.
So given the above, say that you have some code like this that does nothing but loop a random number of times and print the sum:
func sum(x int) {
sum := 0
for i := 0; i < x; i++ {
sum += i
}
fmt.Println(sum)
}
if you use goroutines like
go sum(100)
go sum(200)
go sum(300)
go sum(400)
will the goroutines run one by one if you only have one thread?
A compilation and tidying of all of creker's comments.
Preemptive means that kernel (runtime) allows threads to run for a specific amount of time and then yields execution to other threads without them doing or knowing anything. In OS kernels that's usually implemented using hardware interrupts. Process can't block entire OS. In cooperative multitasking thread have to explicitly yield execution to others. If it doesn't it could block whole process or even whole machine. That's how Go does it. It has some very specific points where goroutine can yield execution. But if goroutine just executes for {} then it will lock entire process.
However, the quote doesn't mention recent changes in the runtime. fmt.Println(sum) could cause other goroutines to be scheduled as newer runtimes will call scheduler on function calls.
If you don't have any function calls, just some math, then yes, goroutine will lock the thread until it exits or hits something that could yield execution to others. That's why for {} doesn't work in Go. Even worse, it will still lead to process hanging even if GOMAXPROCS > 1 because of how GC works, but in any case you shouldn't depend on that. It's good to understand that stuff but don't count on it. There is even a proposal to insert scheduler calls in loops like yours
The main thing that Go's runtime does is it gives its best to allow everyone to execute and don't starve anyone. How it does that is not specified in the language specification and might change in the future. If the proposal about loops will be implemented then even without function calls switching could occur. At the moment the only thing you should remember is that in some circumstances function calls could cause goroutine to yield execution.
To explain the switching in Akavall's answer, when fmt.Printf is called, the first thing it does is checks whether it needs to grow the stack and calls the scheduler. It MIGHT switch to another goroutine. Whether it will switch depends on the state of other goroutines and exact implementation of the scheduler. Like any scheduler, it probably checks whether there're starving goroutines that should be executed instead. With many iterations function call has greater chance to make a switch because others are starving longer. With few iterations goroutine finishes before starvation happens.
For what its worth it. I can produce a simple example where it is clear that the goroutines are not ran one by one:
package main
import (
"fmt"
"runtime"
)
func sum_up(name string, count_to int, print_every int, done chan bool) {
my_sum := 0
for i := 0; i < count_to; i++ {
if i % print_every == 0 {
fmt.Printf("%s working on: %d\n", name, i)
}
my_sum += 1
}
fmt.Printf("%s: %d\n", name, my_sum)
done <- true
}
func main() {
runtime.GOMAXPROCS(1)
done := make(chan bool)
const COUNT_TO = 10000000
const PRINT_EVERY = 1000000
go sum_up("Amy", COUNT_TO, PRINT_EVERY, done)
go sum_up("Brian", COUNT_TO, PRINT_EVERY, done)
<- done
<- done
}
Result:
....
Amy working on: 7000000
Brian working on: 8000000
Amy working on: 8000000
Amy working on: 9000000
Brian working on: 9000000
Brian: 10000000
Amy: 10000000
Also if I add a function that just does a forever loop, that will block the entire process.
func dumb() {
for {
}
}
This blocks at some random point:
go dumb()
go sum_up("Amy", COUNT_TO, PRINT_EVERY, done)
go sum_up("Brian", COUNT_TO, PRINT_EVERY, done)
Well, let's say runtime.GOMAXPROCS is 1. The goroutines run concurrently one at a time. Go's scheduler just gives the upper hand to one of the spawned goroutines for a certain time, then to another, etc until all are finished.
So, you never know which goroutine is running at a given time, that's why you need to synchronize your variables. From your example, it's unlikely that sum(100) will run fully, then sum(200) will run fully, etc
The most probable is that one goroutine will do some iterations, then another will do some, then another again etc.
So, the overall is that they are not sequential, even if there is only one goroutine active at a time (GOMAXPROCS=1).
So, what's the advantage of using goroutines ? Plenty. It means that you can just do an operation in a goroutine because it is not crucial and continue the main program. Imagine an HTTP webserver. Treating each request in a goroutine is convenient because you do not have to care about queueing them and run them sequentially: you let Go's scheduler do the job.
Plus, sometimes goroutines are inactive, because you called time.Sleep, or they are waiting for an event, like receiving something for a channel. Go can see this and just executes other goroutines while some are in those idle states.
I know there are a handful of advantages I didn't present, but I don't know concurrency that much to tell you about them.
EDIT:
Related to your example code, if you add each iteration at the end of a channel, run that on one processor and print the content of the channel, you'll see that there is no context switching between goroutines: Each one runs sequentially after another one is done.
However, it is not a general rule and is not specified in the language. So, you should not rely on these results for drawing general conclusions.
#Akavall Try adding sleep after creating dumb goroutine, goruntime never executes sum_up goroutines.
From that it looks like go runtime spawns next go routines immediately, it might execute sum_up goroutine until go runtime schedules dumb() goroutine to run. Once dumb() is scheduled to run then go runtime won't schedule sum_up goroutines to run, as dumb runs for{}

Why doesn't Go's LockOSThread lock this OS thread?

The documentation for runtime.LockOsThread states:
LockOSThread wires the calling goroutine to its current operating system thread. Until the calling goroutine exits or calls UnlockOSThread, it will always execute in that thread, and no other goroutine can.
But consider this program:
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
runtime.GOMAXPROCS(1)
runtime.LockOSThread()
go fmt.Println("This shouldn't run")
time.Sleep(1 * time.Second)
}
The main goroutine is wired to the one available OS thread set by GOMAXPROCS, so I would expect that the goroutine created on line 3 of main will not run. But instead the program prints This shouldn't run, pauses for 1 second, and quits. Why does this happen?
From the runtime package documentation:
The GOMAXPROCS variable limits the number of operating system threads that can execute user-level Go code simultaneously. There is no limit to the number of threads that can be blocked in system calls on behalf of Go code; those do not count against the GOMAXPROCS limit.
The sleeping thread doesn't count towards the GOMAXPROCS value of 1, so Go is free to have another thread run the fmt.Println goroutine.
Here's a Windows sample that will probably help you understand what's going on. It prints thread IDs on which goroutines are running. Had to use syscall so it works only on Windows. But you can easily port it to other systems.
package main
import (
"fmt"
"runtime"
"golang.org/x/sys/windows"
)
func main() {
runtime.GOMAXPROCS(1)
runtime.LockOSThread()
ch := make(chan bool, 0)
go func(){
fmt.Println("2", windows.GetCurrentThreadId())
<- ch
}()
fmt.Println("1", windows.GetCurrentThreadId())
<- ch
}
I don't use sleep to prevent runtime from spawning another thread for sleeping goroutine. Channel will block and just remove goroutine from running queue. If you execute the code you will see that thread IDs are different. Main goroutine locked one of the threads so the runtime has to spawn another one.
As you already know GOMAXPROCS does not prevent the runtime from spawning more threads. GOMAXPROCS is more about the number of threads that can execute goroutines in parallel. But more threads can be created for goroutines that are waiting for syscall to complete, for example.
If you remove runtime.LockOSThread() you will see that thread IDs are equal. That's because channel read blocks the goroutine and allows the runtime to yield execution to another goroutine without spawning new thread. That's how multiple goroutines can execute concurrently even when GOMAXPROCS is 1.
GOMAXPROCS(1) which causes you to have one ACTIVE M (OS thread) to be present to server the go routines (G).
In your program there are two Go routines, one is main, and the other is fmt.Println. Since main routine is in sleep, M is free to run any go routine, which in this case fmt.Println can run.
That looks like correct behavior to me. From what I understand the LockOSThread() function only ties all future go calls to the single OS thread, it does not sleep or halt the thread ever.
Edit for clarity: the only thing that LockOSThread() does is turn off multithreadding so that all future GO calls happen on a single thread. This is primarily for use with things like graphics API's that require a single thread to work correctly.
Edited again.
If you compare this:
func main() {
runtime.GOMAXPROCS(6)
//insert long running routine here.
go fmt.Println("This may run almost straight away if tho long routine uses a different thread")
}
To this:
func main() {
runtime.GOMAXPROCS(6)
runtime.LockOSThread()
//insert long running routine here.
go fmt.Println("This will only run after the task above has completed")
}
If we insert a long running routine in the location indicated above then the first block may run almost straight away if the long routine runs on a new thread, but in the second example it will always have to wait for the routine to complete.

Lua Script coroutine

Hi need some help on my lua script. I have a script here that will run a server like application (infinite loop). Problem here is it doesn't execute the second coroutine.
Could you tell me whats wrong Thank you.
function startServer()
print( "...Running server" )
--run a server like application infinite loop
os.execute( "server.exe" )
end
function continue()
print("continue")
end
co = coroutine.create( startServer() )
co1 = coroutine.create( continue() )
Lua have cooperative multithreading. Threads are not swtiched automatically, but must yield to others. When one thread is running, every other thread is waiting for it to finish or yield. Your first thread in this example seems to run server.exe, which, I assume, never finishes until interrupted. Thus second thread never gets its turn to run.
You also run threads wrong. In your example you're not running any threads at all. You execute function and then would try to create coroutine with its output, which naturally would fail. But since you never get back from server.exe you didn't notice this problem yet. Remove those brackets after startServer and continue to fix it.
As already noted, there are several issues with the script that prevent you from getting what you want:
os.execute("...") is blocked until the command is completed and in your case it doesn't complete (as it runs an infinite loop). Solution: you need to detach that process from yours by using something like io.popen() instead of os.execute()
co = coroutine.create( startServer() ) doesn't create a coroutine in your case. coroutine.create call accepts a function reference and you pass it the result of startServer call, which is nil. Solution: use co = coroutine.create( startServer ) (note that parenthesis are dropped, so it's not a function call anymore).
You are not yielding from your coroutines; if you want several coroutines to work together, they need to be cooperating by giving control to each other when appropriate. That's what yield command is for and that's why it's called non-preemptive multithreading. Solution: you need to use a combination of resume and yield calls after you create your coroutine.
startServer doesn't need to be a coroutine as you are not giving control back to it; its only purpose is to start the server.
In your case, the solution may not even need coroutines as all you need to do is: (1) start the server and let it detach from your process (for example, using popen) and (2) work with your process using whatever communication protocol it requires (pipes, sockets, etc.).
There are more complex and complete solutions (like LuaLanes) and also several good descriptions on creating simple coroutine dispatchers.
Your coroutine is not yielding

What is a blocking function?

What is a blocking function or a blocking call?
This is a term I see again and again when referring to Node.js or realtime processing languages.
A function that stops script execution until it ends.
For example, if I had a function in my language that was used to write to a file, like so:
fwrite(file, "Contents");
print("Wrote to file!");
The print statement would only be executed once the file has been written to the disk. The whole program is halted on this instruction. This isn't noticeable for small enough writes, but imagine I had a huge blob to write to the file, one that took many seconds:
fwrite(file, blob);
print("Wrote to file!");
The print statement would only be executed after a few seconds of writting, and the whole program would be stopped for that time. In Node.js, this stuff is done asynchronously, using events and callbacks. Our example would become:
fwrite(file, blob, function() {
print("Wrote to file!");
});
print("Do other stuff");
Where the third parameter is a function to be called once the file has been written. The print statement located after the write function would be called immediately after, whether or not the file has been written yet. So if we were to write a huge enough blob, the output might look like this:
Do other stuff
Wrote to file!
This makes applictions very fast because you're not waiting on a client message, a file write or other. You can keep on processing the data in a parallel manner. This is considered by many one of the strengths of Node.js.
var block = function _block() {
while(true) {
readInputs();
compute();
drawToScreen();
}
}
A blocking function basically computes forever. That's what it means by blocking.
Other blocking functions would wait for IO to occur
a non-blocking IO system means a function starts an IO action, then goes idle then handles the result of the IO action when it happens.
It's basically the difference between a thread idling and sleeping.
A blocking call is one that doesn't allow processing to continue until it returns to the calling thread - this is also referred to as a synchronous call. Asynchronous on the other hand means that threads (and code) can execute at the same time (concurrently).

Resources