Severity: Warning
File: src/Servy.Core/Helpers/ResourceHelper.cs (lines 282-294)
Code:
private bool TerminateBlockingProcesses(string extension, string targetFileName, string targetPath)
{
var isExe = extension.Equals("exe", StringComparison.OrdinalIgnoreCase);
var isDll = extension.Equals("dll", StringComparison.OrdinalIgnoreCase);
if (isExe && !_processKiller.KillProcessTreeAndParents(targetFileName))
return false;
if (isDll && !_processKiller.KillProcessesUsingFile(targetPath))
return false;
return true;
}
Explanation:
For .exe resources, TerminateBlockingProcesses calls KillProcessTreeAndParents(string processName), which (via KillProcessTreeAndParents(string), ProcessKiller.cs lines 173-221) enumerates every process whose ProcessName equals the bare filename (case-insensitive) and kills its tree.
In Servy's deployment model the only .exe resource extracted this way today is Servy.Restarter.exe (Service.cs line 107, ServyRestarterExeFileName = "Servy.Restarter"). A single host commonly runs multiple Servy-managed services, each potentially having a Servy.Restarter.exe instance attached to its own service. When the wrapper service for service A starts and decides the embedded restarter on disk is stale (per ShouldCopyResource, ResourceHelper.cs lines 222-273), it calls TerminateBlockingProcesses("exe", "Servy.Restarter.exe", ...) — and that kills the restarters for services B, C, D, … as collateral damage, even though they are mid-recovery for unrelated processes.
The DLL branch handles this correctly: KillProcessesUsingFile(targetPath) enumerates only processes whose handles point at the specific path. The exe branch has no equivalent path filter.
Suggested fix:
Make the exe branch path-specific too:
if (isExe)
{
// Only kill instances actually using THIS exe path, not every process named the same.
if (!_processKiller.KillProcessesUsingFile(targetPath)) return false;
// OR: enumerate processes and match by MainModule.FileName == targetPath
// before delegating to KillProcessTreeAndParents(int pid, ...).
}
This preserves the file-replacement guarantee while avoiding cross-service damage.
Severity: Warning
File:
src/Servy.Core/Helpers/ResourceHelper.cs(lines 282-294)Code:
Explanation:
For
.exeresources,TerminateBlockingProcessescallsKillProcessTreeAndParents(string processName), which (viaKillProcessTreeAndParents(string), ProcessKiller.cs lines 173-221) enumerates every process whoseProcessNameequals the bare filename (case-insensitive) and kills its tree.In Servy's deployment model the only
.exeresource extracted this way today isServy.Restarter.exe(Service.cs line 107,ServyRestarterExeFileName = "Servy.Restarter"). A single host commonly runs multiple Servy-managed services, each potentially having aServy.Restarter.exeinstance attached to its own service. When the wrapper service for service A starts and decides the embedded restarter on disk is stale (perShouldCopyResource, ResourceHelper.cs lines 222-273), it callsTerminateBlockingProcesses("exe", "Servy.Restarter.exe", ...)— and that kills the restarters for services B, C, D, … as collateral damage, even though they are mid-recovery for unrelated processes.The DLL branch handles this correctly:
KillProcessesUsingFile(targetPath)enumerates only processes whose handles point at the specific path. The exe branch has no equivalent path filter.Suggested fix:
Make the exe branch path-specific too:
This preserves the file-replacement guarantee while avoiding cross-service damage.