wegee2
asked on
Spawned Process in Win 2008 / IIS 7.5 Doesn't Close
Old old website, classic VB ASP, invoking a macro in an MS Access 2000 database.
Set obj = GetObject("e:\data\Admin.m db")
obj.DoCmd.RunMacro "UpdateEmailTable"
Set obj = Nothing
This has run for years without issue until we switched from IIS 6 on Win 2003 over to IIS 7.5 on Win 2008. It still runs okay, but it keeps a lock on the database when it's done and the spawned process does not close.
The macro is a simple one, it deletes a table and imports a spreadsheet in its place.
Symptoms:
1. Upon invoking GetObject, the system spawns an MSACCESS.EXE process under the IIS user.
2. It does the macro work.
3. The process stays open, leaving a hold on the lockfile (Admin.ldb)
If I kill the process manually, I can delete the lock file. If I don't kill the process and the script runs a 2nd time, there will be a second MSACCESS process sitting open. Rinse & repeat until there's a dozen processes and someone notices. I need to fix it.
I've tried adding some lines to the code prior to setting obj = Nothing, both:
obj.DoCmd.Close
and
obj.Close
But neither seems to have the desired effect of closing the process when it is done.
On Win 2003/IIS6 it closes. So I don't know if it's a Win 2008 thing, an IIS 7.5 thing, or some permissions issue with the IIS user being allowed to spawn a process but not close it? I did try making the IIS user a member of Administrators just as a test but it had no effect.
Set obj = GetObject("e:\data\Admin.m
obj.DoCmd.RunMacro "UpdateEmailTable"
Set obj = Nothing
This has run for years without issue until we switched from IIS 6 on Win 2003 over to IIS 7.5 on Win 2008. It still runs okay, but it keeps a lock on the database when it's done and the spawned process does not close.
The macro is a simple one, it deletes a table and imports a spreadsheet in its place.
Symptoms:
1. Upon invoking GetObject, the system spawns an MSACCESS.EXE process under the IIS user.
2. It does the macro work.
3. The process stays open, leaving a hold on the lockfile (Admin.ldb)
If I kill the process manually, I can delete the lock file. If I don't kill the process and the script runs a 2nd time, there will be a second MSACCESS process sitting open. Rinse & repeat until there's a dozen processes and someone notices. I need to fix it.
I've tried adding some lines to the code prior to setting obj = Nothing, both:
obj.DoCmd.Close
and
obj.Close
But neither seems to have the desired effect of closing the process when it is done.
On Win 2003/IIS6 it closes. So I don't know if it's a Win 2008 thing, an IIS 7.5 thing, or some permissions issue with the IIS user being allowed to spawn a process but not close it? I did try making the IIS user a member of Administrators just as a test but it had no effect.
ASKER
Scott, I've tried various other methods of running this macro without using GetObject:
Set objAccess = Server.CreateObject("Acces s.Applicat ion")
objAccess.OpenCurrentDatab ase Server.MapPath("e:\data\Ad min.mdb")
objAccess.DoCmd.RunMacro "UpdateEmailTable"
objAccess.DoCmd.Quit 2 'quit without saving, no prompt
Set objAccess = Nothing
GetObject on the .mdb returns an object of type Application, so I think it's merely a shortcut to the above code.
I've also tried adding the Quit command to the end of the macro itself.
Both of these methods will release its hold on the lock file (good), but the process itself stays open still.
I've read suggestions about the database being corrupt - it is not. That Compact On Close is enabled - it is not. That there are subforms using boolean logic in them - there are none.
The process name is MSACCESS.EXE*32. I'm wondering if it's a problem with svchost closing a 32-bit process. I discount this because if I open the database manually (outside of IIS), it opens Access 2000 under my username, which is the same process name, MSACCESS.EXE*32. The difference being when I close it, the process goes away.
/hair pull
Set objAccess = Server.CreateObject("Acces
objAccess.OpenCurrentDatab
objAccess.DoCmd.RunMacro "UpdateEmailTable"
objAccess.DoCmd.Quit 2 'quit without saving, no prompt
Set objAccess = Nothing
GetObject on the .mdb returns an object of type Application, so I think it's merely a shortcut to the above code.
I've also tried adding the Quit command to the end of the macro itself.
Both of these methods will release its hold on the lock file (good), but the process itself stays open still.
I've read suggestions about the database being corrupt - it is not. That Compact On Close is enabled - it is not. That there are subforms using boolean logic in them - there are none.
The process name is MSACCESS.EXE*32. I'm wondering if it's a problem with svchost closing a 32-bit process. I discount this because if I open the database manually (outside of IIS), it opens Access 2000 under my username, which is the same process name, MSACCESS.EXE*32. The difference being when I close it, the process goes away.
/hair pull
ASKER
Found this as it relates to a similar symptom in a .NET environment:
http://support.microsoft.com/?kbid=317109
But I can't seem to figure out if classic ASP has anything similar. From all I read setting it = nothing in classic will destroy all references to the COM object. Obviously that is not the case here.
Still looking.
http://support.microsoft.com/?kbid=317109
But I can't seem to figure out if classic ASP has anything similar. From all I read setting it = nothing in classic will destroy all references to the COM object. Obviously that is not the case here.
Still looking.
ASKER
Loaded Process Explorer and it appears the process is just sitting idle, which makes sense because its work was completed an hour ago.
For S&G (mostly because I don't know enough to not be dangerous) I created a memory dump of the still-running MSACCESS.EXE*32 process and opened it in WinDbg.
The call stack:
00 : ntdll!ZwWaitForWorkViaWork erFactory+ 0xa
01 : wow64!Wow64EmulateAtlThunk +0x1c993
02 : wow64!Wow64SystemServiceEx +0xd7
03 : wow64cpu!TurboDispatchJump AddressEnd +0x2d
04 : wow64!Wow64SystemServiceEx +0x1ce
05 : wow64!Wow64LdrpInitialize+ 0x429
06 : ntdll!RtlIsDosDeviceName_U +0x24c87
07 : ntdll!LdrInitializeThunk+0 xe
For S&G (mostly because I don't know enough to not be dangerous) I created a memory dump of the still-running MSACCESS.EXE*32 process and opened it in WinDbg.
The call stack:
00 : ntdll!ZwWaitForWorkViaWork
01 : wow64!Wow64EmulateAtlThunk
02 : wow64!Wow64SystemServiceEx
03 : wow64cpu!TurboDispatchJump
04 : wow64!Wow64SystemServiceEx
05 : wow64!Wow64LdrpInitialize+
06 : ntdll!RtlIsDosDeviceName_U
07 : ntdll!LdrInitializeThunk+0
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
I thought I had it nailed. The Access.Application object has a property .hWndAccessApp which returns the window handle of the running process. However, there’s nothing that tells you what the process ID is. There is a function in user32 called GetWindowThreadProcessId that will take a window handle and return the thread ID and, optionally, the process ID. However, you can’t call it from vbscript directly. VB6 you can declare it, vbscript you cannot. The workaround is to create a COM object to call it for you, but that’s a lot of work for what I think is very minimal return. It would be the IDEAL solution because I could then get the exact process ID and terminate it specifically rather than looping through looking for the process to terminate it.
Anyway, I'm satisfied enough with this solution to not bother the EE community any longer with it. Hopefully when we migrate this to .NET & MSSQL, this becomes a non-issue anyway.
Anyway, I'm satisfied enough with this solution to not bother the EE community any longer with it. Hopefully when we migrate this to .NET & MSSQL, this becomes a non-issue anyway.
ASKER
This ultimately kills the dangling process. No actual methods on the object itself will do it.
I'd try
DIM DB AS DATABASE
SET DB = OPENDATABASE (YOURPATH)
'--- run your query
db.close
set db = nothing
Scott C