diff --git a/tests/integration/codexprocess.nim b/tests/integration/codexprocess.nim index 4a0e1c6b..67adfae7 100644 --- a/tests/integration/codexprocess.nim +++ b/tests/integration/codexprocess.nim @@ -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 diff --git a/tests/integration/hardhatprocess.nim b/tests/integration/hardhatprocess.nim index c8e06835..82d34fce 100644 --- a/tests/integration/hardhatprocess.nim +++ b/tests/integration/hardhatprocess.nim @@ -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 diff --git a/tests/integration/nodeprocess.nim b/tests/integration/nodeprocess.nim index 40bfdd5c..827a4b0f 100644 --- a/tests/integration/nodeprocess.nim +++ b/tests/integration/nodeprocess.nim @@ -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" diff --git a/tests/integration/scripts/winkillhardhat.sh b/tests/integration/scripts/winkillhardhat.sh new file mode 100644 index 00000000..32730d7d --- /dev/null +++ b/tests/integration/scripts/winkillhardhat.sh @@ -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 \ No newline at end of file