I have two versions of a minimal web server.
Both execute an infinite loop that receives incoming requests and creates a thread to service each request.
One version simply starts executing that infinite loop.
The other version creates a special thread to execute the infinite loop, and the main program then drops into a standard Windows GetMessage/DispatchMessage loop.
Neither version has a GUI or a console window, they both simply run invisibly, and there's no mechanism coded to make the programs quit (ie, deliberately exit any of their loops).
Any guesses as to why one version uses the extra thread plus GetMessage/DispatchMessage?
It could be habit, based on the habits of the developers of the respective versions. Someone more accustomed to GUI coding might be more likely to add the GetMessage/DispatchMessage code. They may have started with a standard template and adjusted to create the specific project.
Or it could be deliberate -- maybe someone anticipated adding a GUI or some housekeeping tasks in the main thread. Or maybe a watchdog mechanism, where if the infinite loop were to crash (due to an uncaught exception, for instance) the main thread would automatically restart the loop.
I could be way off base, but the question does ask for guesses.
Related
Since Smalltalk scheduling is non-preemptive, processes must explicitly yield or wait on a semaphore
Does this mean that one object entering an infinite loop could stall the entire system?
the loop can be interrupted at any time. Even an atomic loop like [true] whileTrue can be interrupted before "executing" the true object
By what can it be interrupted?
It is the Virtual Machine who may interrupt the image. Under a normal execution flow, the VM is basically sending messages, one after the other. However, certain events may impact the natural flow of execution by interrupting it, if needed. While concrete examples may change from one dialect to the other, these usually correspond to OS events that need to be communicated to the image for their consideration.
An interruption may also be caused if the VM is running out of memory. In this case it will interrupt the image requesting it to do garbage collection.
Loops are interesting because they have the semantics of regular messages, so what happens is that the block of code inside the loop is evaluated (#value & friends) every time the loop repeats. So, you should think of loops as regular messages. However, this semantics is usually optimized so the re-evaluation is not explicitly requested by a Smalltalk message. In that case the VM will check for interruptions before executing the block. Thus, if you run
[true] whileTrue
before designating the object true as the current receiver (in this case, of no message) the VM will check whether there is any interrupt to pay attention to (in the same way it checks for interruptions before starting to execute any given method).
Most dialects implement some "break" keystroke that would produce a "halt" and open a debugger for the programmer to recover manual control.
Note that, depending on the dialect, an interruption may only consist of the signaling of a semaphore. This will have the effect of moving the waiting process (if any) to the ready queue of the ProcessScheduler. So, the intended "routine" may not run immediately but change to the ready state for the next time there is a process switch (at that level of priority).
The last example that comes to mind is the StackOverflow exception (no pun intended), where the VM realizes that it is running out of stack space and interrupts the image by signaling an exception.
You may also think of the #messageNotUnderstood: as an interruption generated by the VM when it realizes that an object has received a message for which is has no implementation. In this case, the natural flow will change so that the object will receive the message #messageNotUnderstood: with the actual message as the argument.
One more thing. Whether a loop may or may not stall the system depends on the priority of the process it is running. If the loop is running with low priority an interruption that awakes a process of higher priority will take precedence and be run while the loop is sent to sleep. By the same logic, if your endless loop runs in a process at a higher priority no interruption will stop it.
Yes, it is super simple to just run
[ true ] whileTrue: [ ]
and you won't be able to do anything else.
Pharo has a "ripcord" when you press comand + . on Mac. For Windows or Linux it's either alt or control. This action should halt the thing that you are running and allow you to intervene.
I have a call to an external program that opens a "modal" window, since it's in the same thread as the main loop it blocks redrawing of the underlying window.
The program runs as a separate process and I am communicating with the program via pipes.
From what I've read it's bad practice to have an additional main loop, so what is the correct way to avoid this lockup?
The question is how to make a separate thread in my own program to do the communication with that program without blocking the entire main loop.
Use a non blocking API to run the external program, such as GSubprocess https://developer.gnome.org/gio/stable/GSubprocess.html or the lower level spawn API https://developer.gnome.org/glib/stable/glib-Spawning-Processes.html
You could also use a thread but the above APIs are much easier.
You have to somehow return control to the main loop while the subprocess runs, that's the bottom line.
I'm porting an ancient VB6 program to C#/.Net. I don't know VB6 very well and I'm asking this to understand it better.
The old VB6 program had a main course of program execution, but it also had lots of event handlers either for socket events or for timer events and the handlers for these often manipulated shared resources, e.g., common global variables, whenever they woke up and ran.
Nonetheless the old program seemed to run OK.
Trying to do this same architecture in C# is disastrous because event handlers for the socket or timers are called by the system in different threads from the main application thread and result in frequent exceptions like "The calling thread cannot access this object because a different thread owns it.", not to mention more subtle problems. Most of my work in the conversion is re-architecting the program to make it thread-safe, and eliminating the original program's heavy use of global variables.
My question is Do VB6 event handlers run in separate threads? If so how did VB6 ever get away with this? Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
Apartment-Model Threading in Visual Basic
If you want the gritty details, research apartment threading models in COM. VB6 basically uses COM and it's built-in implicity threading models to treat single threads as message-passing entities. It simplifies thread-safety, but underneath you are sacrificing a lot of overhead by basically treating all method calls as queued service calls.
All of your code basically runs in a container that implements COM service calls. If you've ever worked with something written in VB6 in another language, you can interact with them via COM, usually.
Do VB6 event handlers run in separate threads?
Not really, because there aren't separate threads. Your code runs on a single thread, wrapped in the service-like architecture I described above. Most of what you talk to that is threaded is other COM objects which have their own apartments. So to communicate back and forth, you are basically doing RPC calls when the threads talk to each other: you aren't directly manipulating them.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
The "timer" is on a separate thread created for the timer, but when it calls into your code, you are guaranteed not to interrupt any other functions, because the function calls are basically queued one at a time in the thread.
My question is Do VB6 event handlers run in separate threads?
Common answer: No.
Real answer: Yes, if you make nasty Win32 calls to spawn more threads. The odds of doing this correctly are close to zero. I don't think I've ever seen it in real code.
Among other things, the VB6 program had a timer that woke up every 4 seconds, manipulated some global variables and went back to sleep, while the main program was doing its thing. I can't understand why this didn't result in collisions.
When the timer wakes up, it puts a message in the UI's queue. When the UI goes idle, it processes the message and runs the event on the UI thread.
You can do the same thing in WinForms if you use the right timer.
To Matt Wilko, DoEvents is VB6 implementing a virtual cooperative multithreading thing. What's a thread, something that can be interupted to run other code. When you use DoEvents you interupt the execution of your code, when the CPU does multithreading it preempts your code. The effect is the same. One done by VB6 runtime and one by the CPU.
The effect is the same. YOU NEED TO SYNCHRONISE ACCESS TO GLOBAL OBJECTS and VARIABLES.
Your event Handlers aren't supposed to run too long. Each event is queued and run one at a time.
Also the way to multithread a VB6 thing is to put other things in a COM Exe file with a asynchronous model. The exe calls back when finished.
I'm contemplating writing a program like Qt's Mandelbrot Sample. In that sample, GUI/Worker thread separation is established where calculation is performed on a background thread. As iteratively more detail is provided, image data is sent back to the GUI window for display. If the mouse pans or zoom while an in-progress calculation is still happening...the old calculation is "canceled" and doesn't run any more.
(Note: There is no way to safely just kill a running thread in C++. So the worker has to check a restart boolean every now and again during points in the calculation loop...in a cooperative multitasking way.)
As a new-to-Haskell person, I'm wondering exactly what sort of recourse someone would have for even a very simple version of this. I've read about Functional Reactive Programming and it makes (some) sense to me. But I haven't found anything about asking for a long calculation, getting progressive results from that calculation over time, and then pulling the rug out from under the calculation based on something the user did to start a new one.
This is what I found in searching, and I'm not sure how relevant it is:
How to write Ctrl-C handler in Haskell?
Does killThread in GHC's concurrency have a safety that other systems don't; making it okay to use for cancellation of this form? The computations being killed would not be involved in GUI operations--their work would all be where GHC was in control. But they still would need a way to progressively communicate their progress back to the interface somehow. So during that signaling it might be using some OS facility and be an "unsafe time".
Yes, and no. killThread is GHC is a super-fancy way of setting that restart boolean. Each "capability" in the GHC run-time has a slot for asynchronous exceptions that the run-time checks from time to time and, if it isn't empty will throw the exception in that capability.
Normally, this will kill that thread, although I believe the exception can be caught and recovered from. Also, while asynchronous exceptions are masked in a thread, this slot is not checked; as soon as the masking ends, the slot is checked and the exception is thrown. This is true whether it is just a lightweight thread (started via forkIO) or a full OS thread (started via forkOS). forkProcess is its own beast, though I've heard on IRC that it is safer than the documentation makes it out to be.
In a Haskell-only program, you would communicate back with an IORef, MVar, or TVar (various levels of functionality and safety). (Most of) The exposed operations on these references mask asynchronous exceptions for small windows so that the references are not left in a "bad" state. If you need to communicate in some other fashion, you will be responsible for properly masking/unmasking asynchronous exceptions to avoid curruption of your communication channel (and minimizing the "uninterruptable" window).
I have a threading problem with Delphi. I guess this is common in other languages too. I have a long process which I do in a thread, that fills a list in main window. But if some parameters change in the mean time, then I should stop current executing thread and start from the beginning. Delphi suggests terminating a thread by setting Terminated:=true and checking for this variable's value in the thread. However my problem is this, the long executing part is buried in a library call and in this call I cannot check for the Terminated variable. Therefore I had to wait for this library call to finish, which affects the whole program.
What is the preferred way to do in this case? Can I kill the thread immediately?
The preferred way is to modify the code so that it doesn't block without checking for cancellation.
Since you can't modify the code, you can't do that; you either have to live with the background operation (but you can disassociate it from any UI, so that its completion will be ignored); or alternatively, you can try terminating it (TerminateThread API will rudely terminate any thread given its handle). Termination isn't clean, though, like Rob says, any locks held by the thread will be abandoned, and any cross-thread state protected by such locks may be in a corrupted state.
Can you consider calling the function in a separate executable? Perhaps using RPC (pipes, TCP, rather than shared memory owing to same lock problem), so that you can terminate a process rather than terminating a thread? Process isolation will give you a good deal more protection. So long as you aren't relying on cross-process named things like mutexes, it should be far safer than killing a thread.
The threads need to co-operate to achieve a graceful shutdown. I am not sure if Delphi offers a mechanism to abort another thread, but such mechanisms are available in .NET and Java, but should be considered an option of last resort, and the state of the application is indeterminate after they have been used.
If you can kill a thread at an arbitrary point, then you may kill it while it is holding a lock in the memory allocator (for example). This will leave your program open to hanging when your main thread next needs to access that lock.
If you can't modify the code to check for termination, then just set its priority really low, and ignore it when it returns.
I wrote this in reply to a similar question:
I use an exception-based technique
that's worked pretty well for me in a
number of Win32 applications.
To terminate a thread, I use
QueueUserAPC to queue a call to a
function which throws an exception.
However, the exception that's thrown
isn't derived from the type
"Exception", so will only be caught by
my thread's wrapper procedure.
I've used this with C++Builder apps very successfully. I'm not aware of all the subtleties of Delphi vs C++ exception handling, but I'd expect it could easily be modified to work.