continue a good cause started by Jimmy Nilsson saying “Don’t you hate being told what to do and not to do, without knowing the reason why?” As for now the time has come to STA, the only apartment model available from VB 6 and formers. On the one hand Microsoft proclaims VB 6 and STA components as stable enterprise architecture for the middle tier with bold font in titles of MSDN. On the other hand you can find lots of strong restrictions for STA under COM+ written with smaller font in the very technical articles of the same MSDN. C’est la vie. But as a rule there is only a restriction mentioned and very rarely you can find a short explanation why it is not worth doing so. Keep in mind that some restrictions can be fatal for your architecture and you can never predict when and where it will happen. You should learn all the restrictions as well as investigate their real reasons and possible effects before picking out some particular architecture. So measure thrice and cut once before taking the final decision. And of course don’t buy bold titles of MSDN and other advertisement. You have to learn to read between the lines. And now I will help you to study a piece of Microsoft day-to-day advice Don’t make blocking calls from STA. Terse and clear.
ABSTRACT
First of all, there are two kinds of blocking calls. The first one is an implicitly blocking call. That happens when you are making an outgoing call to other components outside of the caller apartment or context and are synchronously waiting for the call to return back. Explicitly blocking call occurs when you are calling Sleep or WaitForSingleObject or something like that. If you are making a blocking call of any type, the message loop of the caller’s STA thread is blocked, which forces the activity’s workflow to get blocked as well while it is waiting for the blocking call to return. During this time, the message loop cannot serve any other instances that live on that thread.The same is for components marked as Both. Don’t ever forget any Both component can be created from an STA component at any time and therefore it can also get into an STA apartment and thus it can also perform as a usual STA component.
COM+ STA pool has 7 + X threads and potentially can grow up to 10 * X, where X is a number of CPUs on the board. That is if we had 8 CPUs that pool would hold 15 threads initially and 80 threads at the maximum under stress. Suppose all the 15 threads are already busy handling incoming COM calls. After that COM+ starts to reuse these existing 15 threads. Such a technique is called multiplexing.
Michael McKeown, MS Engineer writes in MSDN as follows: Unlike MTS, COM+ binds up to five activities to a thread. That’s only a half of the truth. Actually COM+ operates in the following way. Let we have 1 CPU on the board. In that case COM+ distributes all incoming requests among 8 threads existing from the very beginning. After these existing 8 threads got 5 activities per thread (i.e. 40 activities) COM+ creates the ninth thread and bounds the next 5 activities to it. After that COM+ creates the tenth thread and bounds the next 5 activities to it. Now that COM+ has reached the upper limit of threads it begins to multiplex all incoming activities among 10 threads. That is COM+ binds up to five activities to a thread only when there are 8 initial threads. The upper limit is not five activities per thread. The upper limit is unknown actually. More precisely the upper limit is stack overflow but we won’t forestall.
Under MTS if all the threads are busy making out-of-apartment calls MTS queues incoming calls until some thread gets available to handle a call. But COM+ operates otherwise. Suppose an STA component receives an incoming call A, starts execution on the STA thread and makes out-of-apartment call. COM intermediate layer (so-called COM-channel) enters the thread’s modal message loop and feels ready to receive and handle another COM request to the same STA apartment while working RPC thread makes a real blocking call to the target component and actually waits for that blocking call to return. Another incoming call B to the same apartment can now be also served. Activity A is still waiting for return. Suppose activity B gets an incoming call B, starts execution and makes out-of-apartment call as well. Here lies the key point for understanding. Activity A won’t return control of the STA thread until Activity B completes handling of call B entirely. Imagine, all the components are of the same type and make out-of-apartment calls. That means A calls out, B calls out, C calls out and so on and so forth. So A waits for B to complete, B in its turn waits for C to complete etc. We’ve got a LIFO structure (Last In First Out). Execution time of A consists of its own execution time and B + C + etc execution time. This is the price we are forced to pay for the possibility to work around the blocking caused by out-of-apartment call from STA.
For those who make explicitly blocking call COM+ provides CoWaitForMutlipleHandles function. If the caller resides in an STA, CoWaitForMutlipleHandles enters the STA message modal loop, and the loop will continue to dispatch messages using the thread’s message filter. If no message filter is registered for the thread, the default COM message processing is used. If the calling thread resides in an MTA, CoWaitForMutlipleHandles just forwards the call to Win32 API function MsgWaitForMutlipleObjects.
And that is the double blessing. Can you see where the danger is coming up? Everything said above was just suspense.
ARCHITECTURE
Any serious contemporary n-tier architecture includes number of system services along with main business components. Before launching business logic it should log on to the system, get some context object which will be passed afterwards to all the underlying components ensuring exchange of system parameters and fulfilling other tasks like error collecting. Also it has to check permissions whether that particular user has the right to fulfill the requested task. It has to check if that particular user has bought the license necessary to fulfill the desired feature. As a rule it is system services, which are responsible for all this system functionality. Underlying business objects, as a rule, also make out-of-apartment calls, for example, to the united Locking Service. The services possess several advantages over other variants of implementation. The main advantage is that services can handle incoming requests when nobody is logged on to the system. Anyway, several calls are to be made out-of-process from any tier of n-tier architecture.
It would make sense to take out-of-proc callers out of COM+ but, you know, developers are fond of placing DLLs under COM+. They like that not only because COM+ ensures transactions, synchronization and other stuff. COM+ suggests approved dllhost.exe as a host for DLL to be available remotely. That’s also one of the main reasons where to place components to. So, accept the inevitable. You have got some COM+ components making out-of-apartment, out-of-context, out-of-process or even out-of-machine calls. There would seem to be nothing terrible about it. Even if you trusted titles of MSDN and created all the components in VB that is as STA components. Even in that case, there still would seem to be nothing awful. Slow performance under stress, that is all what it looks. Okay let’s conduct a simple but nice (as usual) test.
TEST
It will take you half an hour to write a test revealing the behavior of STA objects making out-of calls under COM+.
1. Create some COM EXE. Name that CmpExe. It does not matter what language you use and whether you make it as service or not.
2. Expose its method via COM interface, let’s name it MtdExe.
3. Write the code of MtdExe sleeping for a while, say, 300 ms and returning after that.
4. Create some COM DLL CmpDll in VC++ with public method MtdDll. Mark that as STA. Keep in mind you could also create that component with VB6 but further you will need to insert pieces of Assembler to measure things.
5. Write the code of MtdDll creating that COM EXE and calling its method MtdExe.
6. Place that COM DLL under COM+ in a server application.
Now that we have got a simple infrastructure emulating a real system we can stress that system. Use Microsoft Application Center Test from VS.NET Enterprise Edition or something like that. As for me, I used simple bomber process whose goal was just to create a new thread, so that later that thread creates the COM DLL, calls its method MtdDll and measures time of the call.
FIRST RESULTS
Launch that and see after a while system will just hang. On my machine system hangs after about 200 calls to MtdDll. CPU activity drops to near zero and the system remains in that state forever. The system hangs during the call from CmpDll to CmdExe. Just hangs silently.
INVESTIGATION
After I had installed debug symbols for Windows 2000 Service Pack 3, adjusted AD+ (MS KB PSS ID Number: 286350 HOWTO: Use Autodump+ to Troubleshoot “Hangs” and “Crashes”)and worked with WinDbg I caught the cause. The reason was a stack overflow in dllhost.exe process (COM+ Application). Let’s see the whole picture of stack exhausting.
As expected, all STA COM DLLs shared a thread pool of 10 threads (from 7+1 to 10*1). Below comes a sample table (Fig. 1) that shows how free stack space was changing when the COM DLL was serving 50 requests. Each line corresponds to one thread; the first column shows stack space while serving the first request (for each thread), and so forth. To avoid excessive clattering of the table, when stack space didn’t change in comparison to the previous measurement, the actual value is replaced with an austerisk. Mind you, that initial stack size, allocated by COM for every thread, is 256K, and tests have shown that a single request consumes 20K of stack space (at the point of logging, that is the beginning of MtdExe).
Thread 1 |
139264 |
118784 |
* |
* |
* |
* |
|||||||||
Thread 2 |
143360 |
122880 |
* |
* |
* |
* |
* |
||||||||
Thread 3 |
143360 |
122880 |
* |
* |
* |
* |
|||||||||
Thread 4 |
143360 |
122880 |
* |
* |
* |
||||||||||
Thread 5 |
139264 |
118784 |
* |
* |
* |
||||||||||
Thread 6 |
139264 |
118784 |
* |
* |
* |
||||||||||
Thread 7 |
143360 |
122880 |
* |
* |
|||||||||||
Thread 8 |
139264 |
118784 |
* |
* |
|||||||||||
Thread 9 |
131072 |
110592 |
* |
* |
|||||||||||
Thread 10 |
135168 |
114688 |
* |
* |
Fig. 1
Number of Requests |
Minimum Free Stack Space |
100 |
110592 |
150 |
86016 |
200 |
Stack Overflow |
Fig. 2 shows the flashpoint where stack gets overflowed.
Below are the functions that were used to obtain the total stack size and the available stack space.
DWORD GetStackSize()
{
Here is the function that returns COM-related flags variable from the TLS. It also proved useful in the course of the investigation for example, to find out whether the thread is running in Main STA or not.
enum OLETLSFLAGS
{


Data Observability Explained
Data is the lifeblood of any successful business, as it is the driving force behind critical decision-making, insight generation, and strategic development. However, due to its intricate nature, ensuring the


Logitech G502 Software: Optimize and Customize Your Gear
One of the most significant surges of the 21st century is gaming. Gaming is more popular than ever before thanks to innovative new consoles, high-tech PC setups, mobile gaming improvements,


Different Types of Data Models Explained with Examples
In the modern world, data is everything and everywhere. With so much access to technology, data has become a valuable resource for any business. Albeit a complex one. Data is


Revolutionizing Search: A Glimpse Into Google’s Generative Experience
Google is revolutionizing the search experience as we know it with its latest generative experience. No longer will you be bound by the limitations of traditional keyword searching. Now, you


10 Productivity Hacks to Supercharge Your Business in 2023
Picture this: your team working seamlessly, completing tasks efficiently, and achieving goals with ease. Sounds like too good to be true? Not at all! With our productivity hacks, you can


GM Creates Open Source uProtocol and Invites Automakers to Adopt It: Revolutionizing Automotive Software Development.
General Motors (GM) recently announced its entry into the Eclipse Foundation. The Eclipse Foundation is a prominent open-source software foundation. In addition, GMC announced its contribution of “uProtocol” to facilitate


What is Metadata?
What is metadata? Well, It’s an odd concept to wrap your head around. Metadata is essentially the secondary layer of data that tracks details about the “regular” data. The regular


What We Should Expect from Cell Phone Tech in the Near Future
The earliest cell phones included boxy designs full of buttons and antennas, and they only made calls. Needless to say, we’ve come a long way from those classic brick phones


The Best Mechanical Keyboards For Programmers: Where To Find Them
When it comes to programming, a good mechanical keyboard can make all the difference. Naturally, you would want one of the best mechanical keyboards for programmers. But with so many


The Digital Panopticon: Is Big Brother Always Watching Us Online?
In the age of digital transformation, the internet has become a ubiquitous part of our lives. From socializing, shopping, and learning to more sensitive activities such as banking and healthcare,


Embracing Change: How AI Is Revolutionizing the Developer’s Role
The world of software development is changing drastically with the introduction of Artificial Intelligence and Machine Learning technologies. In the past, software developers were in charge of the entire development


The Benefits of Using XDR Solutions
Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved