AttachThreadToClarion() - Whats not included?

In the docs, it says

This AttachThreadToClarion function must be called by the launching thread to attach it to the thread handler in the runtime library. Without this call, any attempt within the thread to use thread dependent Clarion functions and operations (all string and decimal operators, BIND/EVALUATE, ERROR/ERRORCODE, most FILE statements, etc.) will cause a program termination.

Is there a list of what’s not included?

I’m assuming, so could be wrong, that the Program clw is called, so global vars, classes and everything you’ll find beneath the PROGRAM statement is initialised.

The app hangs on this line of code

    Access:ServiceControlLog.SetName(GFP:ServiceControlLogFile)


    Compile('_***_',ISEQ:Debug)
    DSS('SetFilenames : Access:ServiceControlLog.FileName (' & Clip(Access:ServiceControlLog.FileName) & ')' )
    DSS('SetFilenames : Access:ServiceControlLog.FileNameValue (' & Clip(Access:ServiceControlLog.FileNameValue) & ')' )
    _***_

Its the first time, I start to make changes to the filemanager for a file, and at this stage the file isnt even open but cant rule out Window’s Defender causing the problems despite having exceptions set up for the service I’m building.

Disabling Windows Defender Realtime protection doesnt make a change either, and to be honest this laptop is playing up big time, to the point I might wipe it and reinstall Windows 11 again.

TIA

If you are calling into Clarion code from another language, then either the caller must call AttachThreadToClarion() or the first line in the function should call it.

Failure to do this will result in a GPF in almost all cases. The subset of functions that can be called without doing this are so minor and trivial that that code should just be written in the other language.

Longer version;

There is a lot of code that executes when a thread starts. So threads that are started by the Clarion START command do this for you. As is common with Clarion a LOT of things happen under the hood.

If a thread is started using the Windows API, or by another language, then this startup does not happen. Thats really bad.

Things like global, threaded, variables, FILEs, and objects are not allocated memory. Dictionary objects are not initialized.

In other words, the call is not optional. It is required.

I get all that, but should AttachThreadToClarion() initialise all the global classes that are found in the Program section of an app?

Edit.

So I can get the filename of the inimgr class out, so it looks like classes are being initialised properly with the caveat the inimgr class is a simple class, and there’s more trickery going on with the filemanager classes, namely Hide:Access… which I need to investigate further.

Edit.
Using psExec -s -i cmd.exe which opens a new command line window where I can then run C60dbx - p , I can step into the debugger and see the filemanagers appear to be initialised, but as I’m using a sleep(30000) in the ServiceMain to have the time to attach the debugger, and on this super slow laptop, I keep timing out with the servcie control manager.

Anyway still trying to figure it out why the service hangs on the first filemanager line in servicemain.

I suffered from unexplainable behaviour including some ‘freezes’ .. I now add a SLEEP(500) immediately after the call to AttachThreadToClarion and hey presto : no more freezes

Its not freezes Im suffering from with the service app, its just a case of finding a way to attach the debugger when its running as a service as local system account.

The psexec line opens a dos window with system level permission, the highest apart from Ring 0.

psexec -s -i cmd.exe

This lets me then run the debugger from command line with permission high enough to debug the service.

One alternative I’ve yet to try is install the service using a normal windows account instead of local system account.

I would then have the requisite permissions to debug the service, a case of less is more.

So when I can next get back on the laptop, cuz Im still having to sleep rough on the streets of Exeter, UK since Jan4th, I will give the service account permission changes a go.

This way I can then try adding a run() command into the ServiceMain code that calls the debugger and then sleeps().

These havent worked

Run('C60DBX -p ' & ISWA_GetCurrentProcessId( GLLA:GetCurrentProcessId ) )
Sleep(10000)
Run('psexec -i -s cmd.exe C60DBX -p ' & ISWA_GetCurrentProcessId( GLLA:GetCurrentProcessId ) )
Sleep(10000)
Run('psexec -i -s C60DBX -p ' & ISWA_GetCurrentProcessId( GLLA:GetCurrentProcessId ) )
Sleep(10000)
Run('psexec -i -s C60DBX -p ' & ISWA_GetCurrentProcessId( GLLA:GetCurrentProcessId ) )
a# = ISWA_DebugBreak( GLLA:DebugBreak )

Not even adding the service flag SERVICE_INTERACTIVE_PROCESS to interact with the desktop made it possible to use the debugger. It was visible in the task manager but not something I could make visible and interact with.

So the only way to debug a service using the local system account aka NT Authority\LocalService is to use

psexec -i -s cmd.exe

and then in this new dos window running with System level access is to use

 C60DBX -p <pid>

but the service never leaves the sleep(x) line.

I run DebugView++ manually “as Administrator” whilst my service is running as the local system account, without admin rights it doesn’t display anything from my service.

Yeah I do that with normal Debugview, but in order to use the Clarion Debugger requires more steps and hoops to jump through.