Open justinc1 opened 7 years ago
i tried to fix this, on iperf 2.0.10 from http://sourceforge.net/projects/iperf2. There are two problematic threads: reporter_spawn for iperf client and server listener_spawn for iperf server only
Approach: set flag that main_will_exit. Then, reporter_spawn will return once flag is set. main can exit afterwards. The main should also join on reporter_spawn, otherwise we might have problems (main exited sortly before reporter_spawn, and reporter_spawn trying to acccess data destroyed by main).
Same for listener_spawn, except that that one is waiting in accept. To get it woken up, main does one additional connect. Ugly, but seems to work. There is mentioned that shutdown(sock, how) should wake up thread in accept(), but this doesn't seem to work on OSv.
I can try to finalize the patch, if it is worth - I didn't yet try to remove pthread_detach, assemble list of all started threads, and at the end let main() join on all of them.
But maybe, even current patch might be better than VM which doesn't exit once work is done? main waits on the mentioned threads to set 'worker_exited' flag, and than comes silly say 0.1 sec delay, so that other threads have additional time to exit.
The patches I was talking about. I pushed code to https://github.com/justinc1/iperf2/tree/osv-2.0.10 , so I will not delete it by accident.
A couple of comments on what you wrote above:
It is fine that the main thread returns, it doesn't really need to wait for the other threads, because the program is not unloaded (and its memory not freed, static objects not destructed, etc.) and unless main() deliberately frees something before returning (maybe it does, I'm really not familiar with that program) it could be fine.
I don't understand how shutdown() works on a socket in accept(), since shutdown() is supposed to work on a connected socket. But maybe this trick works on Linux? Would be interesting to check (and if it does work on Linux, we need to support it on OSv too...).
The classic way to interrupt accept is either through signals (ugly...) or, better, using a non-blocking accept and a select()/poll(): You select() the server socket and a second file descriptor (e.g., a pipe) which you use to notify it to wake up, and call accept() only when the server socket it ready.
But I wonder if it's a big problem if we just call exit(0) at the end, and have the entire OSv exit, always, when iperf finishes :-)
I guess problem with iperf and signals is that iperf expects signal handler to rain in the main thread (it does some configuration to ensure that). This is not true on OSv, and in some cases I saw quite a few signal_handler threads started. So ctrl+C does not stop VM.
I will use iperf more often in near future, and if the "just call exit()" works well for me, I will send a patch with it.
I noticed that orig iperf 2.0.5 does not exit VM once done. Some threads are left over, and some extra work is required to get them terminated.
OSv - master at
Host:
OSv:
gdb:
So after main() returns, one app thread is left, and VM doesn't terminate - app is still considered to be up. Correct?