After app quits, background process lingers?

A customer has reported this happening on his Windows 10 system. He tells me that after he quits my app (made with the latest Xojo + MBS plugins) the Task Manager shows the app moving into the “Background processes” category and using up some small percent of CPU cycles. He added that if he opens multiple copies, only the first one quit shows this problem. The others quit normally.

I have a Windows 10 system running here and I can’t reproduce this at all. I quit the app and it’s gone, as it should be. So I’ve told him this has to do with something peculiar about his system. Any ideas what that could be? He says this doesn’t happen with any other software, only mine.

What background process?
Do you run something via Shell class?

I’ve seen this already. Can’t properly find the issue, but seems like on Windows Xojo has more problems to shutdown running threads and/or timers.

[quote=432492:@Christian Schmitz]What background process?
Do you run something via Shell class?[/quote]

The Background process has the same name as the application.

The app does not call any shell commands.

On Windows there is a group of timers polling MIDI input. They get stopped before quitting of course, but maybe this is the cause. But if that’s true then why can’t I reproduce it?

I’m sure you’ve looked this up (for those that don’t know) a background process is listed as a process that currently has no active UI, so something where all windows are closed but the program is still running by some other means, e.g. stuck in a thread or sitting on a tray. My initial checks would include:

Do you use a tray icon?
Do you use threads?
Do you use declares?
Do you save settings to disk on quit?
Do you use HTML viewers?
Do you have App.AutoQuit = False in your app?

[quote=432500:@]I’m sure you’ve looked this up (for those that don’t know) a background process is listed as a process that currently has no active UI, so something where all windows are closed but the program is still running by some other means, e.g. stuck in a thread or sitting on a tray. My initial checks would include:

Do you use a tray icon?
Do you use threads?
Do you use declares?
Do you save settings to disk on quit?
Do you use HTML viewers?
Do you have App.AutoQuit = False in your app?[/quote]

A fair enough list (except I wouldn’t include saving settings to disk here unless it involves something out of the ordinary). All already ruled out in this case, of course.

The only thing I could find is that some timers may not be destroyed, so I added some code to destroy them for sure on quit. Since the problem doesn’t happen on my system of course I have no way to check if this makes any difference. Have to see what the customer says.

The only reason I mentioned file saving is because their anti-virus might be holding the file open, locked or something so your code can’t get past the file save and shutdown.

Failing all that, sprinkle in some file logging checkpoints to see where its getting/not getting etc to see what might be keeping it running.

A fair point, and good advice; thank you :slight_smile:

In case anyone else runs into this problem, here is a workaround:

[code]Public Sub KillWindowsProcess()
// kill the app, only on Windoze

// this works but will kill any other application running which has the same name
’ dim s as new shell
’ dim n as string = AppShortVersion
#if DebugBuild then n = “Debug” + n
’ s.Execute( “Taskkill /IM “+n+”.exe /F” )

// this works but may not be 64-bit compatible
#if TargetWin32 then
’ Declare Function GetCurrentProcessId Lib “Kernel32” () As UInt32
’ dim PID as UInt32 = GetCurrentProcessId()
’ dim s as new shell
’ s.Execute(“Taskkill /PID " + str(PID) + " /F”)
#endif

// this works for both 32-bit and 64-bit builds
’ and will not kill any same-named applications
dim p as new WindowsProcessStatisticsMBS
dim pID as integer = p.ProcessID
dim s as new shell
s.Execute(“Taskkill /PID " + str(pID) + " /F”)
End Sub
[/code]

Call this from the App.Close event for Windows builds only. Put some code after the call, or it might not work. Here’s my example which works:

[code] // … after everything has been is cleaned up
’ stop lingering process on Windows
#if TargetWin32 then
App.Log( “killing Windows process” )
KillWindowsProcess
#endif

’ debug
App.Log( “quitting” )[/code]

App.Log is my own logging system which writes to a text file if a debugging switch is on. For Mac, “quitting” as the last message, and for Windows it will be “killing Windows process”. This is a serious issue because the lingering background process uses up the same amount of RAM as the running app.

1 Like

Its a shame you couldn’t track the issue down with logging, it certainly was an odd one. This will do the same as taskkill /f but doesn’t require a shell or plugins but you will have a race condition getting to App.Log after calling it. However, if shell works for you its all good :slight_smile:

Declare Function GetCurrentProcess Lib "Kernel32.dll" () As Integer Declare Function TerminateProcess Lib "Kernel32.dll" (hProcess As Integer, uExitCode As UInt32) As Int32 Call TerminateProcess(GetCurrentProcess(), 0)