Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/changelog.d/4293.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Check access process on windows
3 changes: 3 additions & 0 deletions src/ansys/mapdl/core/cli/stop.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,13 +187,16 @@ def _can_access_process(proc):
True if we can safely access and kill the process
"""
import getpass
import platform

import psutil

try:
# Check if we can access basic process info and if it belongs to current user
current_user = getpass.getuser()
process_user = proc.username()
if platform.system() == "Windows" and "\\" in process_user:
return current_user == process_user.split("\\")[-1]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we should check the domain then too... but I am not sure if that is even the logical thing to do.

return process_user == current_user
except (psutil.AccessDenied, psutil.NoSuchProcess):
# Cannot access process or process doesn't exist
Expand Down
40 changes: 40 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
# SOFTWARE.

import os
import platform
import re
import subprocess
from typing import Callable
Expand Down Expand Up @@ -289,6 +290,45 @@ def mock_kill_process(proc: psutil.Process):
print("✅ Permission handling test passed - no crashes occurred")


@requires("click")
@pytest.mark.skipif(
platform.system() != "Windows", reason="Domain usernames are Windows-specific"
)
def test_pymapdl_stop_with_username_containing_domain(run_cli):
"""Test that pymapdl stop processes when a process username contains DOMAIN information."""
current_user = "someuser"

mock_process = MagicMock(spec=psutil.Process)
mock_process.pid = 12
mock_process.name.return_value = "ansys252"
mock_process.status.return_value = psutil.STATUS_RUNNING
mock_process.cmdline.return_value = ["ansys251", "-grpc", "-port", "50052"]
mock_process.username.return_value = f"DOMAIN\\{current_user}"

killed_processes: list[int] = []

def mock_kill_process(proc: psutil.Process):
"""Track which processes would be killed."""
killed_processes.append(proc.pid)

with (
patch("getpass.getuser", return_value=current_user),
patch("psutil.process_iter", return_value=[mock_process]),
patch("psutil.pid_exists", return_value=True),
patch("ansys.mapdl.core.cli.stop._kill_process", side_effect=mock_kill_process),
):
killed_processes.clear()
output = run_cli("stop --all")

assert "success" in output.lower()

assert killed_processes == [12]

print(
"✅ Domain username handling test passed - processes with domain usernames handled correctly"
)


@requires("click")
@pytest.mark.parametrize(
"arg,check",
Expand Down
Loading