Callback API- client code executed before process terminated

Having problems with building or using CEF's C/C++ APIs? This forum is here to help. Please do not post bug reports or feature requests here.

Callback API- client code executed before process terminated

Postby JozefK » Wed Feb 28, 2024 12:14 pm

Hi, in our case, we are rendering to custom desktop, to be able to do that, we are creating and switching to custom desktop inside render & gpu processes too.
And consequentially, before the application is going to be a shutdown, we need to switch to primary desktop.
Is there any API / callback mechanism to execute client code before the above mentioned processes are gonna to died?
I wasn't able to find such ability / API in M91 & M109. Any idea?

I can imagine there could be some callback OnBeforeProcessTerminated(reason, ...)
JozefK
Techie
 
Posts: 20
Joined: Mon Feb 27, 2017 3:24 pm

Re: Callback API- client code executed before process termin

Postby magreenblatt » Wed Feb 28, 2024 12:28 pm

we are creating and switching to custom desktop inside render & gpu processes

How are you doing that currently?
magreenblatt
Site Admin
 
Posts: 12409
Joined: Fri May 29, 2009 6:57 pm

Re: Callback API- client code executed before process termin

Postby JozefK » Wed Feb 28, 2024 2:40 pm

it's developed by my teammate, so have no detail info :(
From glimpse at code - this WinAPI are used: CreateDesktop / OpenDesktop / SwitchDesktop
Has been told to me:
It has to be switched to custom desktop also in subprocesses to gain success results(in terms of rendering)

In my opinion it could make sense, there is some relation between device context vs render context vs desktop,
so I didn't analyze deeply and was looking for API.
JozefK
Techie
 
Posts: 20
Joined: Mon Feb 27, 2017 3:24 pm

Re: Callback API- client code executed before process termin

Postby ndesktop » Thu Feb 29, 2024 2:15 am

You can do this before calling CefShutdown.

Alternatively, just in case application (let's call it app.exe), for example, crashes and the input desktop remains in your custom one, you can have an additional helper app (app_helper.exe) doing something like this:
- app:
1. starts app_helper running in the default desktop (CreateProcess(Ex) and set STARTUPINFO lpDesktop to L"WinSta0\\Default") with some argument like --parent-pid=GetCurrentProcessId() (the helper can anyway do a CreateToolhelp32Snapshot and find the parent process)
2. create an event name "app.ProcessTerminate.<pid>"
3. run
- app_helper:
1. get the parent pid (and determine if is really app.exe) => parent_pid
2. OpenProcess on parent_pid with SYCNHRONIZE (PROCESS_QUERY_INFORMATION if you plan to call later GetExitCodeProcess - see below) => parent_process
3. format the event name "app.ProcessTerminate.<parent_pid>", and do OpenEvent with SYNCHRONIZE => parent_process_terminate_event
4a. WaitForSingleObject(parent_process, INFINITE) or WaitForSingleObject(parent_process_terminate_event, INFINITE) if you just do wait on parent process or parent process termination event
4b. wait for app termination with loop: create an invisible window and do a message loop similar to this:
Code: Select all
bool need_restore_desktop = false;
bool end_loop = false;
while(!end_loop) {
  DWORD wait_result = MsgWaitForMultipleObjects(1, &pprocess, FALSE, INFINITE, QA_ALLINPUT);
  if(wait_result == WAIT_OBJECT_0) {
    end_loop = true;
    // parent process or parent process term event signaled; possibly call here GetExitCodeProcess
    need_restore_desktop = true;
    break;
  }
  else if(wait_result == WAIT_OBJECT_0 + 1) {
    MSG msg;
    while(PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) {
      TranslateMessage(&msg); // optional
      DispatchMessage(&msg);
      if(msg.message == WM_ENDSESSION) {
        // Windows is shuttin, but read below *
        need_restore_desktop = true;
        end_loop = true;
      }
    }
  }
  // ...
}

if(need_restore_desktop) {
  RestoreDesktop(); // see below
}

4. OpenInputDesktop and GetUserObjectInformation(with UOI_NAME) to determine the name of the input desktop
4a. if it is the default desktop, do nothing and close
4b. if it is *not* the default desktop, then OpenDesktop on the default desktop and SwitchDesktop to the default desktop handle.
A sample implementation of desktop restoring could be simply this (inside app_helper):
Code: Select all
void RestoreDesktop() {
  HDESK hDefaultDesktop = GetThreadDesktop(GetCurrentThreadId()); // we know we run in default; or if doubt, OpenDesktop on WinSta0\Default
  if(hDefaultDesktop != NULL) {
    SwitchDesktop(hDefaultDesktop);
    CloseDesktop(hDefaultDesktop);
  }
}


WM_ENDSESSION (and WM_QUERYENDSESSION) caveats.
*Sometimes* (yes, I know) WM_(QUERY)ENDSESSION do NOT arrive on the message loop of the application running in a non-default desktop. I saw this on Windows 7, although I did not checked thoroughly on this later.
I do have a mechanism that traps these messages in the helper app running in the default desktop and forward them in the non-default desktop via IPC so the non-default desktop app can close (otherwise all sorts of nastiness happened, at least at that time when I notices this).

Hope that helps.
ndesktop
Master
 
Posts: 756
Joined: Thu Dec 03, 2015 10:10 am

Re: Callback API- client code executed before process termin

Postby JozefK » Fri Mar 01, 2024 8:57 am

Sure ndesktop, it definitely helps, thanks. We'll consider this explicit approach.
JozefK
Techie
 
Posts: 20
Joined: Mon Feb 27, 2017 3:24 pm


Return to Support Forum

Who is online

Users browsing this forum: No registered users and 217 guests