mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-01-04 22:43:12 +00:00
fix: forcefully kill windows hardhat processes after termination
On windows, termination of hardhat processes would not actually kill the process, and then closing the process' streams would then hang the calling nim process. To get around this, the process is now killed externally using a script, winkillhardhat.sh. This script first queries open processes by inspecting the command line value of all "node.exe" processes, searching for "vendor/codex-contracts-eth" and for the port parameter it was started with. After querying, the process is killed using the `Stop-Process` powershell command (passing the pid of the windows process).
This commit is contained in:
parent
7006c6c727
commit
e3d0304ef7
@ -116,6 +116,11 @@ method stop*(node: CodexProcess) {.async: (raises: []).} =
|
||||
trace "stopping codex client"
|
||||
await procCall NodeProcess(node).stop()
|
||||
|
||||
if not node.process.isNil:
|
||||
trace "closing node process' streams"
|
||||
await node.process.closeWait()
|
||||
trace "node process' streams closed"
|
||||
|
||||
if client =? node.client:
|
||||
await client.close()
|
||||
node.client = none CodexClient
|
||||
|
||||
@ -94,6 +94,17 @@ method start*(
|
||||
HardhatProcessError, "failed to start hardhat process: " & parent.msg, parent
|
||||
)
|
||||
|
||||
proc port(node: HardhatProcess): ?int =
|
||||
var next = false
|
||||
for arg in node.arguments:
|
||||
# TODO: move to constructor
|
||||
if next:
|
||||
return parseInt(arg).catch.option
|
||||
if arg.contains "--port":
|
||||
next = true
|
||||
|
||||
return none int
|
||||
|
||||
proc startNode*(
|
||||
_: type HardhatProcess,
|
||||
args: seq[string],
|
||||
@ -108,6 +119,7 @@ proc startNode*(
|
||||
|
||||
var arguments = newSeq[string]()
|
||||
for arg in args:
|
||||
# TODO: move to constructor
|
||||
if arg.contains "--log-file=":
|
||||
logFilePath = arg.split("=")[1]
|
||||
else:
|
||||
@ -126,6 +138,7 @@ proc startNode*(
|
||||
|
||||
await hardhat.start()
|
||||
|
||||
# TODO: move to constructor
|
||||
if logFilePath != "":
|
||||
hardhat.logFile = some hardhat.openLogFile(logFilePath)
|
||||
|
||||
@ -146,13 +159,63 @@ method onOutputLineCaptured(node: HardhatProcess, line: string) =
|
||||
discard logFile.closeFile()
|
||||
node.logFile = none IoHandle
|
||||
|
||||
proc killHardhatByPort(
|
||||
port: int
|
||||
): Future[CommandExResponse] {.
|
||||
async: (
|
||||
raises: [
|
||||
AsyncProcessError, AsyncProcessTimeoutError, CancelledError, ValueError, OSError
|
||||
]
|
||||
)
|
||||
.} =
|
||||
let path = splitFile(currentSourcePath()).dir / "scripts" / "winkillhardhat.sh"
|
||||
let cmd = &"{absolutePath(path)} killvendorport {port}"
|
||||
trace "Forcefully killing windows hardhat process", port, cmd
|
||||
return await execCommandEx(cmd, timeout = 5.seconds)
|
||||
|
||||
proc closeProcessStreams(node: HardhatProcess) {.async: (raises: []).} =
|
||||
when not defined(windows):
|
||||
if not node.process.isNil:
|
||||
trace "closing node process' streams"
|
||||
await node.process.closeWait()
|
||||
trace "node process' streams closed"
|
||||
else:
|
||||
# Windows hangs when attempting to close hardhat's process streams, so try
|
||||
# to kill the process externally.
|
||||
without port =? node.port:
|
||||
error "Failed to get port from Hardhat args"
|
||||
return
|
||||
try:
|
||||
let cmdResult = await killHardhatByPort(port)
|
||||
if cmdResult.status > 0:
|
||||
error "Failed to forcefully kill windows hardhat process",
|
||||
port, exitCode = cmdResult.status, stderr = cmdResult.stdError
|
||||
else:
|
||||
trace "Successfully killed windows hardhat process by force",
|
||||
port, exitCode = cmdResult.status, stdout = cmdResult.stdOutput
|
||||
except ValueError, OSError:
|
||||
let eMsg = getCurrentExceptionMsg()
|
||||
error "Failed to forcefully kill windows hardhat process, bad path to command",
|
||||
error = eMsg
|
||||
except CancelledError as e:
|
||||
discard
|
||||
except AsyncProcessError as e:
|
||||
error "Failed to forcefully kill windows hardhat process", port, error = e.msg
|
||||
except AsyncProcessTimeoutError as e:
|
||||
error "Timeout while forcefully killing windows hardhat process",
|
||||
port, error = e.msg
|
||||
|
||||
method stop*(node: HardhatProcess) {.async: (raises: []).} =
|
||||
# terminate the process
|
||||
await procCall NodeProcess(node).stop()
|
||||
|
||||
await node.closeProcessStreams()
|
||||
|
||||
if logFile =? node.logFile:
|
||||
trace "closing hardhat log file"
|
||||
discard logFile.closeFile()
|
||||
|
||||
node.process = nil
|
||||
|
||||
method removeDataDir*(node: HardhatProcess) =
|
||||
discard
|
||||
|
||||
@ -140,39 +140,6 @@ method stop*(
|
||||
warn "failed to kill node process in time, it will be killed when the parent process exits",
|
||||
error = e.msg
|
||||
writeStackTrace()
|
||||
finally:
|
||||
proc closeProcessStreams() {.async: (raises: []).} =
|
||||
trace "closing node process' streams"
|
||||
await node.process.closeWait()
|
||||
trace "node process' streams closed"
|
||||
|
||||
# Windows hangs when attempting to hardhat's process streams,
|
||||
# so try to kill the process externally.
|
||||
# TODO: Chronos gives us an msys2 processid, and this command is used
|
||||
# to kill a windows processid, so we need to run a command to
|
||||
# get the windows pid from the msys pid first.
|
||||
when defined(windows):
|
||||
if node.name.contains("hardhat"):
|
||||
trace "killing process by id", processId
|
||||
try:
|
||||
let cmdResult =
|
||||
await execCommandEx(&"wmic process where processid={processid} delete")
|
||||
if cmdResult.status > 0:
|
||||
error "failed to kill process by id",
|
||||
processId, exitCode = cmdResult.status, error = cmdResult.stdError
|
||||
else:
|
||||
error "successfully killed process by id",
|
||||
processId, exitCode = cmdResult.status, output = cmdResult.stdOutput
|
||||
except CancelledError as e:
|
||||
discard
|
||||
except AsyncProcessError as e:
|
||||
error "Failed to kill process by id", processId, error = e.msg
|
||||
else:
|
||||
await closeProcessStreams()
|
||||
else:
|
||||
await closeProcessStreams()
|
||||
|
||||
node.process = nil
|
||||
|
||||
trace "node stopped"
|
||||
|
||||
|
||||
110
tests/integration/scripts/winkillhardhat.sh
Normal file
110
tests/integration/scripts/winkillhardhat.sh
Normal file
@ -0,0 +1,110 @@
|
||||
#!/bin/bash
|
||||
|
||||
# List all node.exe processes with command line arguments
|
||||
list_node_processes() {
|
||||
powershell.exe -Command "Get-WmiObject Win32_Process -Filter \"name = 'node.exe'\" | Select-Object ProcessId, Name, CommandLine | Format-Table -AutoSize"
|
||||
}
|
||||
|
||||
# Find node processes containing vendor\codex-contracts-eth in command line
|
||||
find_vendor_node_processes() {
|
||||
echo "Looking for node processes with 'vendor\\codex-contracts-eth' in command line..."
|
||||
powershell.exe -Command "Get-WmiObject Win32_Process -Filter \"name = 'node.exe'\" | Where-Object { \$_.CommandLine -match 'vendor\\\\codex-contracts-eth' } | Select-Object ProcessId, Name, CommandLine | Format-Table -AutoSize"
|
||||
}
|
||||
|
||||
# Find node processes running on a specific port
|
||||
find_node_by_port() {
|
||||
local port=$1
|
||||
echo "Looking for node processes running on port $port..."
|
||||
powershell.exe -Command "Get-WmiObject Win32_Process -Filter \"name = 'node.exe'\" | Where-Object { \$_.CommandLine -match '--port $port' } | Select-Object ProcessId, Name, CommandLine | Format-Table -AutoSize"
|
||||
}
|
||||
|
||||
# Kill all node.exe processes containing vendor\codex-contracts-eth
|
||||
kill_vendor_node_processes() {
|
||||
echo "Finding and killing node.exe processes containing 'vendor\\codex-contracts-eth'..."
|
||||
powershell.exe -Command "
|
||||
\$processes = Get-WmiObject Win32_Process -Filter \"name = 'node.exe'\" | Where-Object { \$_.CommandLine -match 'vendor\\\\codex-contracts-eth' };
|
||||
if (\$processes) {
|
||||
foreach (\$process in \$processes) {
|
||||
Stop-Process -Id \$process.ProcessId -Force;
|
||||
Write-Host \"Killed process \$(\$process.ProcessId)\";
|
||||
}
|
||||
} else {
|
||||
Write-Host \"No matching node.exe processes found\";
|
||||
}
|
||||
"
|
||||
}
|
||||
|
||||
# Kill node.exe process running on a specific port
|
||||
kill_node_by_port() {
|
||||
local port=$1
|
||||
echo "Finding and killing node.exe process running on port $port..."
|
||||
powershell.exe -Command "
|
||||
\$processes = Get-WmiObject Win32_Process -Filter \"name = 'node.exe'\" | Where-Object { \$_.CommandLine -match '--port $port' };
|
||||
if (\$processes) {
|
||||
foreach (\$process in \$processes) {
|
||||
Stop-Process -Id \$process.ProcessId -Force;
|
||||
Write-Host \"Killed process \$(\$process.ProcessId) running on port $port\";
|
||||
}
|
||||
} else {
|
||||
Write-Host \"No node.exe process found running on port $port\";
|
||||
}
|
||||
"
|
||||
}
|
||||
|
||||
# Kill node.exe process with both vendor string and specific port
|
||||
kill_vendor_node_by_port() {
|
||||
local port=$1
|
||||
echo "Finding and killing node.exe process with 'vendor\\codex-contracts-eth' running on port $port..."
|
||||
powershell.exe -Command "
|
||||
\$processes = Get-WmiObject Win32_Process -Filter \"name = 'node.exe'\" | Where-Object { \$_.CommandLine -match 'vendor\\\\codex-contracts-eth' -and \$_.CommandLine -match '--port $port' };
|
||||
if (\$processes) {
|
||||
foreach (\$process in \$processes) {
|
||||
Stop-Process -Id \$process.ProcessId -Force;
|
||||
Write-Host \"Killed process \$(\$process.ProcessId) running on port $port\";
|
||||
}
|
||||
} else {
|
||||
Write-Host \"No matching node.exe process found running on port $port\";
|
||||
}
|
||||
"
|
||||
}
|
||||
|
||||
# Check if being run directly or sourced
|
||||
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
||||
# If run directly (not sourced), provide command line interface
|
||||
case "$1" in
|
||||
list)
|
||||
list_node_processes
|
||||
;;
|
||||
find)
|
||||
find_vendor_node_processes
|
||||
;;
|
||||
findport)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Usage: $0 findport PORT_NUMBER"
|
||||
exit 1
|
||||
fi
|
||||
find_node_by_port "$2"
|
||||
;;
|
||||
killall)
|
||||
kill_vendor_node_processes
|
||||
;;
|
||||
killport)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Usage: $0 killport PORT_NUMBER"
|
||||
exit 1
|
||||
fi
|
||||
kill_node_by_port "$2"
|
||||
;;
|
||||
killvendorport)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Usage: $0 killvendorport PORT_NUMBER"
|
||||
exit 1
|
||||
fi
|
||||
kill_vendor_node_by_port "$2"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $0 {list|find|findport PORT|killall|killport PORT|killvendorport PORT}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
Loading…
x
Reference in New Issue
Block a user