How to keep a Win64 C++ console app running like a service as it controls other executables? - windows

I have a series of Win64 console apps, one is the "master" and 16 others are the "slaves".
The original version of this logic only had one executable, which when launched with a command line parameter "init" would initialize a very large data set (3gigs) and then sit on the Windows Message Pump waiting for messages requesting analysis of that large data set. When analysis of the data set is needed, that same executable is launched with analysis requesting parameters, and the newly launched executable would find the Window Handle of the already initialized instance of itself, and send the analysis request and parameters to the already initialized instance via the Windows Message WM_COPYDATA. This works like a charm for a single executable architecture.
However, now I have a more powerful system, and I want to run multiple analysis executables at once, each on a different core. So I made a new architecture where there are 16 analysis executables that act as "slaves" to a Manager console application which acts as "master". (FYI, one analysis request can take anywhere from 0.5 to 4.0 seconds - hence my desire to run multiples at once.)
Still using the Windows Messages as my communication means, use of SendMessage() blocks the caller until the message is handled by the receiver. That's no good, because I want these messages to be handled concurrently. So, I tried to use the asynchronous Windows Message functions, such as SendMessageCallback() and SendNotifyMessage(). They either failed or executed in a blocking manner, not concurrently.
More research led me to "Named Shared Memory" as a means of communicating between my executables (essentially a memory-mapped file). So I set that up, and my master is now able to create the Named Shared Memory block, and all my executables are able to request views of that same memory, and via a state machine handling of the data in the Named Shared Memory, I have synchronization between the master and the slaves.
HOWEVER, I am finding that the master and the slaves do not appear to be running continuously.
I'm still using the basic idea of the master is launched via a command line holding analysis parameters, that executable sends a message to the already running version of itself with the Named Shared Memory setup plus the current state of all the slaves, and then an available slave is selected and it's Named Shared Memory resident state machine gets the analysis request.
This portion is working fine. However, the slave(s) appear to be in a sleep or other dormant state, because my modified Windows Message Loop does not appear to be looping.
Here's what my current Windows Message handling loop looks like:
while (1) {
int status = ::GetMessage(&msg, 0, 0, 0);
if (status != 0) {
if (status == -1) return -1
::DispatchMessage(&msg);
}
else if (status == 0)
break;
HandleSharedMemoryDeliveredTasks(); // NOTE: checking Named Shared Memory
}
Placing a break point inside this loop does not get triggered unless a Windows Message is received.
So, I'm wondering how to keep my loop alive so the checking of Named Shared Memory continues without having to send a (blocking) message.
I aware that I'm operating in a problem space where I should convert my master and slave executables into Windows Services. However, I am very, very close to getting this working (it seems), and rewriting to a Windows Service is an area I have no experience.
Also, I am using this in my executables to keep them active (but it does not appear to be helping):
// during program init:
SetThreadExecutationState(ES_CONTINIOUS | ES_SYSTEM_REQUIRED | ES_AWAYMODE_REQUIRED);
Any suggestions how I can "wake up" a slave asynchronously when the master sets their state machine for work, and likewise have the slave "wake up" the master when the work is completed?

Related

Can you identify which processes are using an ncalrpc RPC Endpoint externally?

When our devs are trying to debug a C++/Winrt ncalrpc RPC server after attaching the newly built and running server process to a VS2017 debugger, they can't breakpoint to new or modified lines of code even if enabling breakpointing to code that isn't exactly the same; it produces an unexpected symbol error message inside the IDE.
I was informed by a team member this was happening due to lingering RPC connections to the RPC Endpoints from other apps and services that use the core service. I don't know a lot about RPC but have been reading up. Checking the core service's source seems to indicate that they're doing everything correctly for stopping the server,
RPC_STATUS rs = 0;
rs = RpcMgmtStopServerListening(NULL);
//...
rs = RpcServerUnregisterIf(RPC_IF_SPEC, nullptr, 0);
//...
rs = RpcEpUnregister(RPC_IF_SPEC, BindingVector, nullptr);
But to be honest it could also be that they should be using rs = RpcServerUnregisterIf(NULL, NULL, 0); instead, I really couldn't say.
Right now we either have to manually track down all the processes that connect to this service and kill/stop them or take the "easy" way out and perform a reboot after installing the new service, allowing us to debug in the correct file locations when attaching the process to VS2017.
My utility idea to get around this was to see if I can generate a list of processes connecting to the RPC Endpoint, nuke them, install the new service, then restart them.
Alternatively this article seems to indicate that avoiding this issue in the first place is possible via something called an Associations, but is somewhat vague on how to do that.
The association itself is reference-counted, and when all references are gone, it stops and closes all connections. Every binding handle and every context handle hold a reference on the association. When all are closed, the association disappears.
Update:
The accepted answer indicates this is not possible with an external process; it is not a way to accomplish this goal with an external process.
RPC has an RpcServerInqCallAttributes function that an RPC server can use during a client call to obtain the client's security context attributes and other information.
You must pass a RPC_CALL_ATTRIBUTES_V2 available only with Windows Vista and higher Windows version (or RPC_CALL_ATTRIBUTES_V3 availble with Windows 8 and higher), so something like this:
// the code depends on the minimal platform you compile for
RPC_CALL_ATTRIBUTES atts = { 0 }; // should map to RPC_CALL_ATTRIBUTES_V2 or RPC_CALL_ATTRIBUTES_V3
atts.Version = RPC_CALL_ATTRIBUTES_VERSION; // should be 2 or 3
atts.Flags = RPC_QUERY_CLIENT_PID;
RpcServerInqCallAttributes(0, &atts);
... pid is in atts.ClientPID ...
This can only be called from the RPC server itself, so you'd have to record all client pids somehow and add some API to the server to be able to list them.

Managing the lifetime of a process I don't control

I'm using Chromium Embedded Framework 3 (via CEFGlue) to host a browser in a third-party process via a plugin. CEF spins up various external processes (e.g. the renderer process) and manages the lifetime of these.
When the third-party process exits cleanly, CefRuntime.Shutdown is called and all the processes exit cleanly. When the third-party process exits badly (for example it crashes) I'm left with CEF executables still running and this (sometimes) causes problems with the host application meaning it doesn't start again.
I'd like a way to ensure that whatever manner the host application exits CefRuntime.Shutdown is called and the user doesn't end up with spurious processes running.
I've been pointed in the direction of job objects (see here) but this seems like it might be difficult to ship in a real solution as on some versions of Windows it requires administrative rights.
I could also set CEF to run in single process mode, but the documentation specifies that this is really for "debugging" only, so I'm assuming shipping this in production code is bad for some reason (see here).
What other options do I have?
Following on from the comments, I've tried passing the PID of the host process through to the client (I can do this by overriding OnBeforeChildProcessLaunch). I've then created a simple watchdog with the following code:
ThreadPool.QueueUserWorkItem(_ => {
var process = Process.GetProcessById(pid);
while (!process.WaitForExit(5000)) {
Console.WriteLine("Waiting for external process to die...");
}
Process.GetCurrentProcess().Kill();
});
I can verify in the debugger that this code executes and that the PID I'm passing into it is correct. However, if I terminate the host process I find that the thread simply dies in a way that I can't control and that the lines following the while loop are never executed (even if I replace it with a Console.WriteLine I never see any more messages printed from this thread.
For posterity, the solution suggested by #IInspectable worked, but in order to make it work I had to switch the implementation of of the external process to use the non-multi threaded message loop.
settings.MultiThreadedMessageLoop = false;
CefRuntime.Initialize(mainArgs, settings, cefWebApp, IntPtr.Zero);
Application.Idle += (sender,e) => {
if (parentProcess.HasExited) Process.GetCurrentProcess().Kill();
CefRuntime.DoMessageLoopWork();
}
Application.Run();

What Windows IPC method is better for short commands?

I need one way IPC method for 2 Windows applications (both on the same machine).
Which one is better in case that my applications are CLI based + windows service.
P.S. I've implemented message queue in destination process (CLI application) in separate thread. And posting my message from source process (GUI application) via PostThreadMessage.
So. When both applications were run from the same user - everything is OK. When I'm running my destination application via Task Scheduler under Local Service user I'm getting 1444 error code (Wrong Thread ID).
Any ideas?
P.P.S. From MSDN
This thread must have the SE_TCB_NAME privilege to post a message to a thread that belongs to a process with the same locally unique identifier (LUID) but is in a different desktop. Otherwise, the function fails and returns ERROR_INVALID_THREAD_ID.
This thread must either belong to the same desktop as the calling thread or to a process with the same LUID. Otherwise, the function fails and returns ERROR_INVALID_THREAD_ID.
So. I should determine how to setup SE_TCB_NAME to my thread from my source process.
WM_COPYDATA message or custom message code (if you don't plan to transfer text or binary data) would work. WM_COPYDATA message lets you transfer binary data and Windows does copying across process boundaries itself.
In GUI -> CLI application you would need to create an invisible window in CLI process to receive messages (if you want messages to be SENT and not POSTed from the GUI application). If you just POST messages from GUI to CLI, then PostThreadMessage() function would be enough and there's no need for a window.
In CLI -> GUI direction there are no complexities at all as the window is already (usually) present in GUI application.
There is also nice solution - Message Queue from boost library.

Are system calls scheduled?

What system process is responsible for executing system call, when user process calls ‘system call’ and the CPU switches to supervisor mode?
Are system calls scheduled by thread scheduler (can CPU switch to executing another system call after getting interrupt)?
What system process is responsible for executing system call?
The system call wrapper(the function you call to perform the system call, yeah it's just a wrapper, not the actually System call) will take the parameters, pass them to the approperiate registers(or on stack, depends on implementation), next it will put the system call number you're requesting in the eax (assuming x86) and finally will call INT 0x80 assembly instruction which is basically telling the OS that it received an interrupt and this interrupt is a system call that needs to be served, which system call to serve is available in the eax and the parameters are in the registers.
(modern implementations stopped using INT because it's expensive in performance and now use SYSENTER and SYSEXIT; the above is still almost the same though)
From the perspective of the scheduler, it makes no difference if you perform a system call or not; the thing is, once you ask the OS for a service(via the x86 instruction INT or SYSENTER and SYSEXIT ) the CPU mode flag will change to a privileged set, then the kernel will perform the task you asked for on behalf of your process and once done, it sets the flag back and returns the execution to the next instruction.
So, from a scheduler point of view, the OS will see no difference when you execute a system call or anything else.
Few notes:
-What I mentioned above is a general description, I am not sure if Windows applies this but if it doesn't, it should be doing something of similar fashion.
-Many System Calls perform blocking tasks(like I/O handling); to make better CPU utilization if your process asks for a blocking system call, the scheduler will let your process wait in the wait-queue till what it requested is ready, meanwhile other processes run on the CPU BUT do not confuse this with anything, the OS did not 'schedule system calls'.
The scheduler's task is to organize tasks, and from its perspective the system call is just a routine that the process is executing.
A final note, some system calls are atomic which means they should be performed without any interruption to their execution, these system calls if interrupted, will be be asked to restart execution once the interrupt's cause is over; still this is far from the scheduling concept.
First question: it depends. Some system calls go to services which are already running (say a network call) as a process. Some system calls result in a new process getting created and then getting scheduled for execution.
Last question: yes windows is a multiprocessing system. The process scheduler handles when a thread runs, for how long, and hardware interrupts can end up causing the running process to release the CPU or a idle process that the hardware is now ready for to get the CPU.
In windows (at least > Win 7 but I think in the past it was true too) a lot of the system services run in processes called svchost. A good application for seeing what is running were is Process Explorer from sys internals. It is like task manager on steroids and will show you all the threads that a given process owns. For finer grained "I called this dos command what happened" details you'd probably want to use a debugging tool where you can step through your call. Generally though you don't have to concern yourself with these things, you make a system call the system knows you aren't ready to continue processing until whatever process is handling that request has returned. Your request might get the CPU right after your process releases it, it might get the CPU 2 days from now but as far as the OS is concerned (or your program should be concerned) it doesn't matter, execution stops and waits for a result unless you are running multithreaded and then it gets really complicated.

Calling a .EXE from Websphere-MQ

This a follow-up based on MQ (Websphere 7) persist message to file system.
How do you set up an .exe program from an MQ support pack (such as the Q utility in MA01) to execute each time a message is received? Can this be setup in MQ Explorer? (We are using 7.0 on Windows 2008/R2).
There are a few ways to do this.
Set the application up under Windows control (since you mentioned the QMgr is on Windows.) The app would run as a service, with recovery options to restart it if the service fails. The application would be programmed (or configured in the case of Q) to process the queue using GETs with a VERY long wait period. Some additional error handling is required to do something sensible when the QMgr is not available. This works great for copying messages to multiple queues but isn't appropriate for queue-to-file since the file would never close.
Run the application as a WebSphere MQ service. Defining the SERVICE object using CONTRIL(QMGR) causes MQ to start the service when the QMgr boots and stop it when the QMgr is shut down. Since the service is a child process of the QMgr, no need to worry about how to handle errors when the QMgr isn't available.
Trigger the program based on non-zero queue depth. Define a process object describing the command to be executed, enable triggering on the queue with TRIGTYPE(FIRST) and run a trigger monitor. Whenever the queue has depth > 0 and no open input handles, the process object fires and executes the command. The thing you start must know how to parse the command line so the easiest thing to do if you have someone else's executable is use a script to start it. The script parses the trigger message and fires off the executable. Or perhaps the script ignores the trigger message and just runs the exe. I generally use Korn Shell or Perl and both are available on Windows.
I wrote an article showing how to keep event queues from filling using a triggered version of Q. The article assumes you want the queues to remain mostly full so uses triggering on depth of about 80%. The same techniques could be used (in a much simpler implementation, by the way) to fire off the Q program whenever the queue depth became non-zero.
UPDATE
Probably should have linked the article. ;-)
Mission:Messaging: Easing administration and debugging with circular queues

Resources