Menubar created at runtime

Tags: #<Tag:0x00007fc0d8ef8378>

Hi,
as a part of per customer, or even per user customization, on some types of windows we provide a custom, configurable menus. We create local menus and items at runtime and use the Clarion’s mechanism that merges them to the global application menu.
Unfortunately, on the windows where we need to add local menu, we do not have a menubar. Despite this, it worked for ages and a menu dynamically created locally, inside a window, appeared in the global menu. However, we have observed more and more frequent hangs of the application when closing quickly one by one (with Esc) the windows that have their own menu. Application hangs somewhere in the ClaRun when leaving a scope of the window procedure (after kill, it cannot terminate the current thread? or cannot switch to another one? deadlock occurs?).
For testing, we added menubars on several windows and with this fix, we do not observe the freezes anymore, but as the system contains hundreds of windows, we cannot add a menubar statically/manually to every window. So we decided to add it dynamically, just before adding the local menu. And here is the crux of the problem - the menubar created at runtime with CREATE does not merge with the global application menubar, but replaces it. That is, it behaves as if it had the NOMERGE attribute set to TRUE and it does not respond to changes to this attribute.

Does anyone experienced a similar problem? Any tips on creating menubars at runtime? Or the problem with application hangs in general?

Best regards,
Andrzej

Another way to think the problem. If you know the global application menu doesnt change, could you not build it into the dynamically created menubar along with what you are already building with your dynamic menubar?

I havent had to merge menubars.
No tips at this stage, dont know enough about your program.
Application hangs in the runtime can be harder to track down. One way, would be to get the app to output pertinent info to debugview. Putting debugview output strings in different parts of the app can help you narrow down what code is being executed right before the hang. Trial and error can help you narrow down the code thats playing up, until eventually you have got the line of code that causes the hang.

I assume, you are familiar with threading, pausing threads if need be, and the implications of running code on multicore cpu’s. Put another way, if you bind your app to one core of a cpu, do you see less application hangs?

API
SetProcessAffinityMask function (winbase.h) - Win32 apps | Microsoft Docs

Quick customer enabled way

Wiki entry on the subject

By binding an app to one cpu core, you stop other threads from getting ahead on another cpu due to its lower workload and not waiting for the other threads to catch up. This results in random crashes which sounds a bit like what you are seeing. Pinning to one cpu, makes the program run like clockwork like the old days with a single core cpu like a 286, 386, Pentium or whatever. Its a work around until the solution can be found as it might not be your code, but a problem with code elsewhere.

Hello Richard,

many thanks for your tips.

The problem with building the global menus into the local menubar is that events fired from this menu are passed directly to the local window procedure instead of the MDI frame.

Binding the process to only one CPU core does not help.

The application hangs somewhere leaving the scope of the last procedure in a thread, after return from that procedure. We cannot narrow the place down any further with the Clarion code.

Best regards,
Andrzej

Ok another way to tackle the problem.

Another app which watches your app and terminates the process and all threads when a hang is detected, eg no more pings or datetime updated in a file (tps or ini) that the watcher app watches.

These api’s can help do this
Process and Thread Functions - Win32 apps | Microsoft Docs

This api should clear all the threads when a hang occurs.
TerminateProcess function (processthreadsapi.h) - Win32 apps | Microsoft Docs

As I have seen an app being debugged and stopped on a breakpoint making other clarion apps using the same runtime also freeze in some situations, making both apps use separate memorycould help isolate the shared runtime freeze. I havent got to the bottom of what causes it, but so far I have observed it happening when two or more apps use the same runtime dlls. I havent tried using a different older runtime, which could be an option for you.

So these api’s should help
Creating Processes - Win32 apps | Microsoft Docs

A possible quick fix could be tracking down this reg key on 32bit Win7, on the 64bit platform, it forces 16bit apps to run in their own separate memory on 32bit Win7, I dont know if something similar exists with 32bit apps on 64bit OS’es.
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\WOW]
“DefaultSeparateVDM”=“yes”

Another quick fix is to update the shortcuts so the “Run in Separate Memory” tick box in shortcuts is ticked. You dont have to use API’s to isolate the apps then.

But this api could be useful.
CreateProcessA function (processthreadsapi.h) - Win32 apps | Microsoft Docs

Have you noticed any patterns with hanging and printing?
This program manifest option to isolate printers might help.
Application Manifests - Win32 apps | Microsoft Docs

Again a quick fix to isolate the app.

Its worth exploring other manifest elements to see if any of those could also help isolate the app a bit more, because I think that can help reduce the number of hangs.
Application Manifest - Win32 apps | Microsoft Docs

So many choices/ways to solve this problem. :grinning:

We use notify and notification make sure that control creation is done in the MDI.

One MDI window services all dynamic windows, a class inside the windows creates the controls and binds to a data source via a wrapper class for files or queues.

That way all your code for managed a dynamic control is in one place and only one MDI windows services all dynamic windows.

So many choices/ways to solve this problem.

Most of them are actually only workarounds for the problem :wink:

At the moment, we have identified windows for which users use the custom/dynamic menus. Fortunately, it turns out to be a small percentage of all windows in the application. Therefore, we decided to manually add empty menu bars to all of these windows to serve as the proper container for dynamically added menus.
If the results of tests performed on only a few windows are confirmed, this should solve the problem.

Best regards,
Andrzej

Let us know how it goes, because we can only offer up possibilities as we dont know your app in detail to further fine tune and eliminate the suggestions that work and dont work. :smiley: