-
-
Notifications
You must be signed in to change notification settings - Fork 30.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix tests failing with The process cannot access the file because it is being used by another process
by force-killing child processes
#101601
Comments
I'd prefer for job and process group support to be integrated into In if sys.platform == 'win32':
kw['createjob'] = True Killing the process in try:
if USE_PROCESS_GROUP:
try:
popen.send_signal_pg(signal.SIGTERM)
try:
popen.wait(5)
except subprocess.TimeoutExpired:
pass
finally:
popen.send_signal_pg(signal.SIGKILL)
elif sys.platform == 'win32':
try:
popen.send_signal_pg(signal.SIGBREAK)
try:
popen.wait(5)
except subprocess.TimeoutExpired:
pass
finally:
popen.terminate_job()
else:
popen.kill()
except ProcessLookupError:
pass
except OSError as exc:
print_warning(f"Failed to kill {what}: {exc!r}") Regarding
if createjob:
self._job_handle = Handle(_winapi.CreateJobObject())
info = {'BasicLimitInformation': {'LimitFlags':
_winapi.JOB_OBJECT_LIMIT_BREAKAWAY_OK}}
_winapi.SetInformationJobObject(self._job_handle,
_winapi.JobObjectExtendedLimitInformation, info)
creationflags |= _winapi.CREATE_SUSPENDED | CREATE_NEW_PROCESS_GROUP
elif _mswindows:
self._job_handle = None Configuring the job with the limit flag The implementation of After spawning the process in if creationflags & CREATE_NEW_PROCESS_GROUP:
self.pgid = pid
else:
self.pgid = None
if self._job_handle is not None:
_winapi.AssignProcessToJobObject(self._job_handle, hp)
_winapi.ResumeThread(ht)
_winapi.CloseHandle(ht) The new def send_signal_pg(self, sig):
"""Send a signal to the process group."""
if self.pgid is None:
raise SubprocessError('no process group assigned')
try:
processes = _winapi.GetConsoleProcessList()
except OSError as e:
if e.winerror == _winapi.ERROR_INVALID_HANDLE:
raise SubprocessError('a console session is required')
raise
if self.pid not in processes:
raise SubprocessError('the process must be in the current '
'console session')
if sig == signal.SIGINT:
ctrl_event = _winapi.CTRL_C_EVENT
elif sig == signal.SIGBREAK:
ctrl_event = _winapi.CTRL_BREAK_EVENT
else:
raise ValueError("Unsupported signal: {}".format(sig))
_winapi.GenerateConsoleCtrlEvent(ctrl_event, self.pgid) A method is needed to forcefully terminate all active processes in the job. def terminate_job(self):
if self._job_handle is None:
raise SubprocessError('no job assigned')
_winapi.TerminateJobObject(self._job_handle, 1) WinAPI It would be nice to also implement a method that returns basic accounting information about the job, such as the number of active processes, how much user/kernel time the job has used, and info about the job's I/O operations. For example: def get_job_info(self):
if self._job_handle is None:
raise SubprocessError('no job assigned')
return _winapi.QueryInformationJobObject(self._job_handle,
_winapi.JobObjectBasicAndIoAccountingInformation) The above would return a dict containing >>> p.get_job_info()
{'BasicInfo': {'TotalUserTime': 1250000, 'TotalKernelTime': 625000, 'ThisPeriodTotalUserTime': 1250000, 'ThisPeriodTotalKernelTime': 625000, 'TotalPageFaultCount': 5163, 'TotalProcesses': 2, 'ActiveProcesses': 2, 'TotalTerminatedProcesses': 0}, 'IoInfo': {'ReadOperationCount': 64, 'WriteOperationCount': 2, 'OtherOperationCount': 995, 'ReadTransferCount': 768540, 'WriteTransferCount': 172, 'OtherTransferCount': 99152}} The implementation of On POSIX, if process_group != -1:
self.pgid = process_group
elif start_new_session:
self.pgid = self.pid
else:
self.pgid = None
def send_signal_pg(self, sig):
"""Send a signal to the process group."""
if self.pgid is None:
raise SubprocessError('no process group assigned')
try:
os.killpg(self.pgid, sig)
except ProcessLookupError:
pass |
Bug report
GitHub Actions continue to sporadically fail with
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'D:\\a\\cpython\\cpython\\build\\test_python_5740�\\test_python_worker_5604�'
.The failure happens when a test creates a child process, shares a test directory with it, and the child outlives its parent.
#99464 was the previous attempt. Now we should try to implement #98219 (comment).
Note: this problem was reported a few times before:
main
branch #97983The text was updated successfully, but these errors were encountered: