mirror of
https://github.com/evennia/evennia.git
synced 2026-03-20 06:46:31 +01:00
2362 lines
No EOL
304 KiB
HTML
2362 lines
No EOL
304 KiB
HTML
|
|
<!DOCTYPE html>
|
|
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>subprocess — Evennia latest documentation</title>
|
|
<link rel="stylesheet" href="../_static/nature.css" type="text/css" />
|
|
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
|
|
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=d75fae25" />
|
|
<link rel="stylesheet" type="text/css" href="../_static/nature.css?v=245aff17" />
|
|
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
|
|
<script src="../_static/documentation_options.js?v=c6e86fd7"></script>
|
|
<script src="../_static/doctools.js?v=9bcbadda"></script>
|
|
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
|
|
<link rel="index" title="Index" href="../genindex.html" />
|
|
<link rel="search" title="Search" href="../search.html" />
|
|
</head><body>
|
|
|
|
|
|
|
|
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../genindex.html" title="General Index"
|
|
accesskey="I">index</a></li>
|
|
<li class="right" >
|
|
<a href="../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../index.html">Evennia latest</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">subprocess</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div class="document">
|
|
|
|
<div class="documentwrapper">
|
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|
<div class="sphinxsidebarwrapper">
|
|
<search id="searchbox" style="display: none" role="search">
|
|
<h3 id="searchlabel">Quick search</h3>
|
|
<div class="searchformwrapper">
|
|
<form class="search" action="../search.html" method="get">
|
|
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
|
|
<input type="submit" value="Go" />
|
|
</form>
|
|
</div>
|
|
</search>
|
|
<script>document.getElementById('searchbox').style.display = "block"</script><h3>Links</h3>
|
|
<ul>
|
|
<li><a href="https://www.evennia.com/docs/latest/index.html">Documentation Top</a> </li>
|
|
<li><a href="https://www.evennia.com">Evennia Home</a> </li>
|
|
<li><a href="https://github.com/evennia/evennia">Github</a> </li>
|
|
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
|
<li>
|
|
<a href="https://discord.gg/AJJpcRUhtF">Discord</a> -
|
|
<a href="https://github.com/evennia/evennia/discussions">Discussions</a> -
|
|
<a href="https://evennia.blogspot.com/">Blog</a>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<div class="bodywrapper">
|
|
<div class="body" role="main">
|
|
|
|
<h1>Source code for subprocess</h1><div class="highlight"><pre>
|
|
<span></span><span class="c1"># subprocess - Subprocesses with accessible I/O streams</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># For more information about this module, see PEP 324.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Copyright (c) 2003-2005 by Peter Astrand <astrand@lysator.liu.se></span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Licensed to PSF under a Contributor Agreement.</span>
|
|
|
|
<span class="sa">r</span><span class="sd">"""Subprocesses with accessible I/O streams</span>
|
|
|
|
<span class="sd">This module allows you to spawn processes, connect to their</span>
|
|
<span class="sd">input/output/error pipes, and obtain their return codes.</span>
|
|
|
|
<span class="sd">For a complete description of this module see the Python documentation.</span>
|
|
|
|
<span class="sd">Main API</span>
|
|
<span class="sd">========</span>
|
|
<span class="sd">run(...): Runs a command, waits for it to complete, then returns a</span>
|
|
<span class="sd"> CompletedProcess instance.</span>
|
|
<span class="sd">Popen(...): A class for flexibly executing a command in a new process</span>
|
|
|
|
<span class="sd">Constants</span>
|
|
<span class="sd">---------</span>
|
|
<span class="sd">DEVNULL: Special value that indicates that os.devnull should be used</span>
|
|
<span class="sd">PIPE: Special value that indicates a pipe should be created</span>
|
|
<span class="sd">STDOUT: Special value that indicates that stderr should go to stdout</span>
|
|
|
|
|
|
<span class="sd">Older API</span>
|
|
<span class="sd">=========</span>
|
|
<span class="sd">call(...): Runs a command, waits for it to complete, then returns</span>
|
|
<span class="sd"> the return code.</span>
|
|
<span class="sd">check_call(...): Same as call() but raises CalledProcessError()</span>
|
|
<span class="sd"> if return code is not 0</span>
|
|
<span class="sd">check_output(...): Same as check_call() but returns the contents of</span>
|
|
<span class="sd"> stdout instead of a return code</span>
|
|
<span class="sd">getoutput(...): Runs a command in the shell, waits for it to complete,</span>
|
|
<span class="sd"> then returns the output</span>
|
|
<span class="sd">getstatusoutput(...): Runs a command in the shell, waits for it to complete,</span>
|
|
<span class="sd"> then returns a (exitcode, output) tuple</span>
|
|
<span class="sd">"""</span>
|
|
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">builtins</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">errno</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">io</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">locale</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">os</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">time</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">signal</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">sys</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">threading</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">warnings</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">contextlib</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">time</span><span class="w"> </span><span class="kn">import</span> <span class="n">monotonic</span> <span class="k">as</span> <span class="n">_time</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">types</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">fcntl</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="n">fcntl</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
|
|
<span class="n">__all__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Popen"</span><span class="p">,</span> <span class="s2">"PIPE"</span><span class="p">,</span> <span class="s2">"STDOUT"</span><span class="p">,</span> <span class="s2">"call"</span><span class="p">,</span> <span class="s2">"check_call"</span><span class="p">,</span> <span class="s2">"getstatusoutput"</span><span class="p">,</span>
|
|
<span class="s2">"getoutput"</span><span class="p">,</span> <span class="s2">"check_output"</span><span class="p">,</span> <span class="s2">"run"</span><span class="p">,</span> <span class="s2">"CalledProcessError"</span><span class="p">,</span> <span class="s2">"DEVNULL"</span><span class="p">,</span>
|
|
<span class="s2">"SubprocessError"</span><span class="p">,</span> <span class="s2">"TimeoutExpired"</span><span class="p">,</span> <span class="s2">"CompletedProcess"</span><span class="p">]</span>
|
|
<span class="c1"># NOTE: We intentionally exclude list2cmdline as it is</span>
|
|
<span class="c1"># considered an internal implementation detail. issue10838.</span>
|
|
|
|
<span class="c1"># use presence of msvcrt to detect Windows-like platforms (see bpo-8110)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">msvcrt</span>
|
|
<span class="k">except</span> <span class="ne">ModuleNotFoundError</span><span class="p">:</span>
|
|
<span class="n">_mswindows</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_mswindows</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="c1"># some platforms do not support subprocesses</span>
|
|
<span class="n">_can_fork_exec</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">{</span><span class="s2">"emscripten"</span><span class="p">,</span> <span class="s2">"wasi"</span><span class="p">,</span> <span class="s2">"ios"</span><span class="p">,</span> <span class="s2">"tvos"</span><span class="p">,</span> <span class="s2">"watchos"</span><span class="p">}</span>
|
|
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">_winapi</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">_winapi</span><span class="w"> </span><span class="kn">import</span> <span class="p">(</span><span class="n">CREATE_NEW_CONSOLE</span><span class="p">,</span> <span class="n">CREATE_NEW_PROCESS_GROUP</span><span class="p">,</span>
|
|
<span class="n">STD_INPUT_HANDLE</span><span class="p">,</span> <span class="n">STD_OUTPUT_HANDLE</span><span class="p">,</span>
|
|
<span class="n">STD_ERROR_HANDLE</span><span class="p">,</span> <span class="n">SW_HIDE</span><span class="p">,</span>
|
|
<span class="n">STARTF_USESTDHANDLES</span><span class="p">,</span> <span class="n">STARTF_USESHOWWINDOW</span><span class="p">,</span>
|
|
<span class="n">STARTF_FORCEONFEEDBACK</span><span class="p">,</span> <span class="n">STARTF_FORCEOFFFEEDBACK</span><span class="p">,</span>
|
|
<span class="n">ABOVE_NORMAL_PRIORITY_CLASS</span><span class="p">,</span> <span class="n">BELOW_NORMAL_PRIORITY_CLASS</span><span class="p">,</span>
|
|
<span class="n">HIGH_PRIORITY_CLASS</span><span class="p">,</span> <span class="n">IDLE_PRIORITY_CLASS</span><span class="p">,</span>
|
|
<span class="n">NORMAL_PRIORITY_CLASS</span><span class="p">,</span> <span class="n">REALTIME_PRIORITY_CLASS</span><span class="p">,</span>
|
|
<span class="n">CREATE_NO_WINDOW</span><span class="p">,</span> <span class="n">DETACHED_PROCESS</span><span class="p">,</span>
|
|
<span class="n">CREATE_DEFAULT_ERROR_MODE</span><span class="p">,</span> <span class="n">CREATE_BREAKAWAY_FROM_JOB</span><span class="p">)</span>
|
|
|
|
<span class="n">__all__</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="s2">"CREATE_NEW_CONSOLE"</span><span class="p">,</span> <span class="s2">"CREATE_NEW_PROCESS_GROUP"</span><span class="p">,</span>
|
|
<span class="s2">"STD_INPUT_HANDLE"</span><span class="p">,</span> <span class="s2">"STD_OUTPUT_HANDLE"</span><span class="p">,</span>
|
|
<span class="s2">"STD_ERROR_HANDLE"</span><span class="p">,</span> <span class="s2">"SW_HIDE"</span><span class="p">,</span>
|
|
<span class="s2">"STARTF_USESTDHANDLES"</span><span class="p">,</span> <span class="s2">"STARTF_USESHOWWINDOW"</span><span class="p">,</span>
|
|
<span class="s2">"STARTF_FORCEONFEEDBACK"</span><span class="p">,</span> <span class="s2">"STARTF_FORCEOFFFEEDBACK"</span><span class="p">,</span>
|
|
<span class="s2">"STARTUPINFO"</span><span class="p">,</span>
|
|
<span class="s2">"ABOVE_NORMAL_PRIORITY_CLASS"</span><span class="p">,</span> <span class="s2">"BELOW_NORMAL_PRIORITY_CLASS"</span><span class="p">,</span>
|
|
<span class="s2">"HIGH_PRIORITY_CLASS"</span><span class="p">,</span> <span class="s2">"IDLE_PRIORITY_CLASS"</span><span class="p">,</span>
|
|
<span class="s2">"NORMAL_PRIORITY_CLASS"</span><span class="p">,</span> <span class="s2">"REALTIME_PRIORITY_CLASS"</span><span class="p">,</span>
|
|
<span class="s2">"CREATE_NO_WINDOW"</span><span class="p">,</span> <span class="s2">"DETACHED_PROCESS"</span><span class="p">,</span>
|
|
<span class="s2">"CREATE_DEFAULT_ERROR_MODE"</span><span class="p">,</span> <span class="s2">"CREATE_BREAKAWAY_FROM_JOB"</span><span class="p">])</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_can_fork_exec</span><span class="p">:</span>
|
|
<span class="kn">from</span><span class="w"> </span><span class="nn">_posixsubprocess</span><span class="w"> </span><span class="kn">import</span> <span class="n">fork_exec</span> <span class="k">as</span> <span class="n">_fork_exec</span>
|
|
<span class="c1"># used in methods that are called by __del__</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_del_safe</span><span class="p">:</span>
|
|
<span class="n">waitpid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">waitpid</span>
|
|
<span class="n">waitstatus_to_exitcode</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">waitstatus_to_exitcode</span>
|
|
<span class="n">WIFSTOPPED</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">WIFSTOPPED</span>
|
|
<span class="n">WSTOPSIG</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">WSTOPSIG</span>
|
|
<span class="n">WNOHANG</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">WNOHANG</span>
|
|
<span class="n">ECHILD</span> <span class="o">=</span> <span class="n">errno</span><span class="o">.</span><span class="n">ECHILD</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">_del_safe</span><span class="p">:</span>
|
|
<span class="n">waitpid</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">waitstatus_to_exitcode</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">WIFSTOPPED</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">WSTOPSIG</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">WNOHANG</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">ECHILD</span> <span class="o">=</span> <span class="n">errno</span><span class="o">.</span><span class="n">ECHILD</span>
|
|
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">select</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">selectors</span>
|
|
|
|
|
|
<span class="c1"># Exception classes used by this module.</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">SubprocessError</span><span class="p">(</span><span class="ne">Exception</span><span class="p">):</span> <span class="k">pass</span>
|
|
|
|
|
|
<div class="viewcode-block" id="CalledProcessError">
|
|
<a class="viewcode-back" href="../api/evennia.server.evennia_launcher.html#evennia.server.evennia_launcher.CalledProcessError">[docs]</a>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">CalledProcessError</span><span class="p">(</span><span class="n">SubprocessError</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Raised when run() is called with check=True and the process</span>
|
|
<span class="sd"> returns a non-zero exit status.</span>
|
|
|
|
<span class="sd"> Attributes:</span>
|
|
<span class="sd"> cmd, returncode, stdout, stderr, output</span>
|
|
<span class="sd"> """</span>
|
|
<div class="viewcode-block" id="CalledProcessError.__init__">
|
|
<a class="viewcode-back" href="../api/evennia.server.evennia_launcher.html#evennia.server.evennia_launcher.CalledProcessError.__init__">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">returncode</span><span class="p">,</span> <span class="n">cmd</span><span class="p">,</span> <span class="n">output</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">returncode</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd</span> <span class="o">=</span> <span class="n">cmd</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">output</span> <span class="o">=</span> <span class="n">output</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">stderr</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="s2">"Command '</span><span class="si">%s</span><span class="s2">' died with </span><span class="si">%r</span><span class="s2">."</span> <span class="o">%</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd</span><span class="p">,</span> <span class="n">signal</span><span class="o">.</span><span class="n">Signals</span><span class="p">(</span><span class="o">-</span><span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="p">))</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="s2">"Command '</span><span class="si">%s</span><span class="s2">' died with unknown signal </span><span class="si">%d</span><span class="s2">."</span> <span class="o">%</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd</span><span class="p">,</span> <span class="o">-</span><span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="s2">"Command '</span><span class="si">%s</span><span class="s2">' returned non-zero exit status </span><span class="si">%d</span><span class="s2">."</span> <span class="o">%</span> <span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="p">)</span>
|
|
|
|
<span class="nd">@property</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">stdout</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Alias for output attribute, to match stderr"""</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">output</span>
|
|
|
|
<span class="nd">@stdout</span><span class="o">.</span><span class="n">setter</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">stdout</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
|
<span class="c1"># There's no obvious reason to set this, but allow it anyway so</span>
|
|
<span class="c1"># .stdout is a transparent alias for .output</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">output</span> <span class="o">=</span> <span class="n">value</span></div>
|
|
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">TimeoutExpired</span><span class="p">(</span><span class="n">SubprocessError</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""This exception is raised when the timeout expires while waiting for a</span>
|
|
<span class="sd"> child process.</span>
|
|
|
|
<span class="sd"> Attributes:</span>
|
|
<span class="sd"> cmd, output, stdout, stderr, timeout</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">cmd</span><span class="p">,</span> <span class="n">timeout</span><span class="p">,</span> <span class="n">output</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd</span> <span class="o">=</span> <span class="n">cmd</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">timeout</span> <span class="o">=</span> <span class="n">timeout</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">output</span> <span class="o">=</span> <span class="n">output</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">stderr</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="s2">"Command '</span><span class="si">%s</span><span class="s2">' timed out after </span><span class="si">%s</span><span class="s2"> seconds"</span> <span class="o">%</span>
|
|
<span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cmd</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">timeout</span><span class="p">))</span>
|
|
|
|
<span class="nd">@property</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">stdout</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">output</span>
|
|
|
|
<span class="nd">@stdout</span><span class="o">.</span><span class="n">setter</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">stdout</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
|
|
<span class="c1"># There's no obvious reason to set this, but allow it anyway so</span>
|
|
<span class="c1"># .stdout is a transparent alias for .output</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">output</span> <span class="o">=</span> <span class="n">value</span>
|
|
|
|
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">STARTUPINFO</span><span class="p">:</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">dwFlags</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">hStdInput</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">hStdOutput</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">hStdError</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">wShowWindow</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">lpAttributeList</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">dwFlags</span> <span class="o">=</span> <span class="n">dwFlags</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">hStdInput</span> <span class="o">=</span> <span class="n">hStdInput</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">hStdOutput</span> <span class="o">=</span> <span class="n">hStdOutput</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">hStdError</span> <span class="o">=</span> <span class="n">hStdError</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">wShowWindow</span> <span class="o">=</span> <span class="n">wShowWindow</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">lpAttributeList</span> <span class="o">=</span> <span class="n">lpAttributeList</span> <span class="ow">or</span> <span class="p">{</span><span class="s2">"handle_list"</span><span class="p">:</span> <span class="p">[]}</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">copy</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">attr_list</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">lpAttributeList</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="s1">'handle_list'</span> <span class="ow">in</span> <span class="n">attr_list</span><span class="p">:</span>
|
|
<span class="n">attr_list</span><span class="p">[</span><span class="s1">'handle_list'</span><span class="p">]</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">attr_list</span><span class="p">[</span><span class="s1">'handle_list'</span><span class="p">])</span>
|
|
|
|
<span class="k">return</span> <span class="n">STARTUPINFO</span><span class="p">(</span><span class="n">dwFlags</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">dwFlags</span><span class="p">,</span>
|
|
<span class="n">hStdInput</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">hStdInput</span><span class="p">,</span>
|
|
<span class="n">hStdOutput</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">hStdOutput</span><span class="p">,</span>
|
|
<span class="n">hStdError</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">hStdError</span><span class="p">,</span>
|
|
<span class="n">wShowWindow</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">wShowWindow</span><span class="p">,</span>
|
|
<span class="n">lpAttributeList</span><span class="o">=</span><span class="n">attr_list</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">Handle</span><span class="p">(</span><span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">closed</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">Close</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">CloseHandle</span><span class="o">=</span><span class="n">_winapi</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">closed</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">closed</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">CloseHandle</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">Detach</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">closed</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">closed</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">return</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"already closed"</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"</span><span class="si">%s</span><span class="s2">(</span><span class="si">%d</span><span class="s2">)"</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="bp">self</span><span class="p">))</span>
|
|
|
|
<span class="fm">__del__</span> <span class="o">=</span> <span class="n">Close</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># When select or poll has indicated that the file is writable,</span>
|
|
<span class="c1"># we can write up to _PIPE_BUF bytes without risk of blocking.</span>
|
|
<span class="c1"># POSIX defines PIPE_BUF as >= 512.</span>
|
|
<span class="n">_PIPE_BUF</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">select</span><span class="p">,</span> <span class="s1">'PIPE_BUF'</span><span class="p">,</span> <span class="mi">512</span><span class="p">)</span>
|
|
|
|
<span class="c1"># poll/select have the advantage of not requiring any extra file</span>
|
|
<span class="c1"># descriptor, contrarily to epoll/kqueue (also, they require a single</span>
|
|
<span class="c1"># syscall).</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">selectors</span><span class="p">,</span> <span class="s1">'PollSelector'</span><span class="p">):</span>
|
|
<span class="n">_PopenSelector</span> <span class="o">=</span> <span class="n">selectors</span><span class="o">.</span><span class="n">PollSelector</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">_PopenSelector</span> <span class="o">=</span> <span class="n">selectors</span><span class="o">.</span><span class="n">SelectSelector</span>
|
|
|
|
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="c1"># On Windows we just need to close `Popen._handle` when we no longer need</span>
|
|
<span class="c1"># it, so that the kernel can free it. `Popen._handle` gets closed</span>
|
|
<span class="c1"># implicitly when the `Popen` instance is finalized (see `Handle.__del__`,</span>
|
|
<span class="c1"># which is calling `CloseHandle` as requested in [1]), so there is nothing</span>
|
|
<span class="c1"># for `_cleanup` to do.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># [1] https://docs.microsoft.com/en-us/windows/desktop/ProcThread/</span>
|
|
<span class="c1"># creating-processes</span>
|
|
<span class="n">_active</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cleanup</span><span class="p">():</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># This lists holds Popen instances for which the underlying process had not</span>
|
|
<span class="c1"># exited at the time its __del__ method got called: those processes are</span>
|
|
<span class="c1"># wait()ed for synchronously from _cleanup() when a new Popen object is</span>
|
|
<span class="c1"># created, to avoid zombie processes.</span>
|
|
<span class="n">_active</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_cleanup</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">_active</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
<span class="k">for</span> <span class="n">inst</span> <span class="ow">in</span> <span class="n">_active</span><span class="p">[:]:</span>
|
|
<span class="n">res</span> <span class="o">=</span> <span class="n">inst</span><span class="o">.</span><span class="n">_internal_poll</span><span class="p">(</span><span class="n">_deadstate</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">maxsize</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">res</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">_active</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">inst</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="c1"># This can happen if two threads create a new Popen instance.</span>
|
|
<span class="c1"># It's harmless that it was already removed, so ignore.</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="n">PIPE</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="n">STDOUT</span> <span class="o">=</span> <span class="o">-</span><span class="mi">2</span>
|
|
<span class="n">DEVNULL</span> <span class="o">=</span> <span class="o">-</span><span class="mi">3</span>
|
|
|
|
|
|
<span class="c1"># XXX This function is only used by multiprocessing and the test suite,</span>
|
|
<span class="c1"># but it's here so that it can be imported when Python is compiled without</span>
|
|
<span class="c1"># threads.</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_optim_args_from_interpreter_flags</span><span class="p">():</span>
|
|
<span class="w"> </span><span class="sd">"""Return a list of command-line arguments reproducing the current</span>
|
|
<span class="sd"> optimization settings in sys.flags."""</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">optimize</span>
|
|
<span class="k">if</span> <span class="n">value</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">+</span> <span class="s1">'O'</span> <span class="o">*</span> <span class="n">value</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">args</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_args_from_interpreter_flags</span><span class="p">():</span>
|
|
<span class="w"> </span><span class="sd">"""Return a list of command-line arguments reproducing the current</span>
|
|
<span class="sd"> settings in sys.flags, sys.warnoptions and sys._xoptions."""</span>
|
|
<span class="n">flag_opt_map</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s1">'debug'</span><span class="p">:</span> <span class="s1">'d'</span><span class="p">,</span>
|
|
<span class="c1"># 'inspect': 'i',</span>
|
|
<span class="c1"># 'interactive': 'i',</span>
|
|
<span class="s1">'dont_write_bytecode'</span><span class="p">:</span> <span class="s1">'B'</span><span class="p">,</span>
|
|
<span class="s1">'no_site'</span><span class="p">:</span> <span class="s1">'S'</span><span class="p">,</span>
|
|
<span class="s1">'verbose'</span><span class="p">:</span> <span class="s1">'v'</span><span class="p">,</span>
|
|
<span class="s1">'bytes_warning'</span><span class="p">:</span> <span class="s1">'b'</span><span class="p">,</span>
|
|
<span class="s1">'quiet'</span><span class="p">:</span> <span class="s1">'q'</span><span class="p">,</span>
|
|
<span class="c1"># -O is handled in _optim_args_from_interpreter_flags()</span>
|
|
<span class="p">}</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">_optim_args_from_interpreter_flags</span><span class="p">()</span>
|
|
<span class="k">for</span> <span class="n">flag</span><span class="p">,</span> <span class="n">opt</span> <span class="ow">in</span> <span class="n">flag_opt_map</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="n">v</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="p">,</span> <span class="n">flag</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">v</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-'</span> <span class="o">+</span> <span class="n">opt</span> <span class="o">*</span> <span class="n">v</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">isolated</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-I'</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">ignore_environment</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-E'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">no_user_site</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-s'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">safe_path</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-P'</span><span class="p">)</span>
|
|
|
|
<span class="c1"># -W options</span>
|
|
<span class="n">warnopts</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">warnoptions</span><span class="p">[:]</span>
|
|
<span class="n">xoptions</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="p">,</span> <span class="s1">'_xoptions'</span><span class="p">,</span> <span class="p">{})</span>
|
|
<span class="n">bytes_warning</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">bytes_warning</span>
|
|
<span class="n">dev_mode</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">dev_mode</span>
|
|
|
|
<span class="k">if</span> <span class="n">bytes_warning</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">warnopts</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">"error::BytesWarning"</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">bytes_warning</span><span class="p">:</span>
|
|
<span class="n">warnopts</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">"default::BytesWarning"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">dev_mode</span><span class="p">:</span>
|
|
<span class="n">warnopts</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s1">'default'</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">opt</span> <span class="ow">in</span> <span class="n">warnopts</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'-W'</span> <span class="o">+</span> <span class="n">opt</span><span class="p">)</span>
|
|
|
|
<span class="c1"># -X options</span>
|
|
<span class="k">if</span> <span class="n">dev_mode</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="s1">'-X'</span><span class="p">,</span> <span class="s1">'dev'</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">opt</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'faulthandler'</span><span class="p">,</span> <span class="s1">'tracemalloc'</span><span class="p">,</span> <span class="s1">'importtime'</span><span class="p">,</span>
|
|
<span class="s1">'frozen_modules'</span><span class="p">,</span> <span class="s1">'showrefcount'</span><span class="p">,</span> <span class="s1">'utf8'</span><span class="p">,</span> <span class="s1">'gil'</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">opt</span> <span class="ow">in</span> <span class="n">xoptions</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">xoptions</span><span class="p">[</span><span class="n">opt</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">value</span> <span class="ow">is</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="n">arg</span> <span class="o">=</span> <span class="n">opt</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">arg</span> <span class="o">=</span> <span class="s1">'</span><span class="si">%s</span><span class="s1">=</span><span class="si">%s</span><span class="s1">'</span> <span class="o">%</span> <span class="p">(</span><span class="n">opt</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="s1">'-X'</span><span class="p">,</span> <span class="n">arg</span><span class="p">))</span>
|
|
|
|
<span class="k">return</span> <span class="n">args</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_text_encoding</span><span class="p">():</span>
|
|
<span class="c1"># Return default text encoding and emit EncodingWarning if</span>
|
|
<span class="c1"># sys.flags.warn_default_encoding is true.</span>
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">warn_default_encoding</span><span class="p">:</span>
|
|
<span class="n">f</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">_getframe</span><span class="p">()</span>
|
|
<span class="n">filename</span> <span class="o">=</span> <span class="n">f</span><span class="o">.</span><span class="n">f_code</span><span class="o">.</span><span class="n">co_filename</span>
|
|
<span class="n">stacklevel</span> <span class="o">=</span> <span class="mi">2</span>
|
|
<span class="k">while</span> <span class="n">f</span> <span class="o">:=</span> <span class="n">f</span><span class="o">.</span><span class="n">f_back</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">f</span><span class="o">.</span><span class="n">f_code</span><span class="o">.</span><span class="n">co_filename</span> <span class="o">!=</span> <span class="n">filename</span><span class="p">:</span>
|
|
<span class="k">break</span>
|
|
<span class="n">stacklevel</span> <span class="o">+=</span> <span class="mi">1</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">"'encoding' argument not specified."</span><span class="p">,</span>
|
|
<span class="ne">EncodingWarning</span><span class="p">,</span> <span class="n">stacklevel</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">flags</span><span class="o">.</span><span class="n">utf8_mode</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="s2">"utf-8"</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">locale</span><span class="o">.</span><span class="n">getencoding</span><span class="p">()</span>
|
|
|
|
|
|
<div class="viewcode-block" id="call">
|
|
<a class="viewcode-back" href="../api/evennia.server.evennia_launcher.html#evennia.server.evennia_launcher.call">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">call</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Run command with arguments. Wait for command to complete or</span>
|
|
<span class="sd"> for timeout seconds, then return the returncode attribute.</span>
|
|
|
|
<span class="sd"> The arguments are the same as for the Popen constructor. Example:</span>
|
|
|
|
<span class="sd"> retcode = call(["ls", "-l"])</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">with</span> <span class="n">Popen</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">as</span> <span class="n">p</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">p</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="n">timeout</span><span class="p">)</span>
|
|
<span class="k">except</span><span class="p">:</span> <span class="c1"># Including KeyboardInterrupt, wait handled that.</span>
|
|
<span class="n">p</span><span class="o">.</span><span class="n">kill</span><span class="p">()</span>
|
|
<span class="c1"># We don't call p.wait() again as p.__exit__ does that for us.</span>
|
|
<span class="k">raise</span></div>
|
|
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">check_call</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Run command with arguments. Wait for command to complete. If</span>
|
|
<span class="sd"> the exit code was zero then return, otherwise raise</span>
|
|
<span class="sd"> CalledProcessError. The CalledProcessError object will have the</span>
|
|
<span class="sd"> return code in the returncode attribute.</span>
|
|
|
|
<span class="sd"> The arguments are the same as for the call function. Example:</span>
|
|
|
|
<span class="sd"> check_call(["ls", "-l"])</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">retcode</span> <span class="o">=</span> <span class="n">call</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">retcode</span><span class="p">:</span>
|
|
<span class="n">cmd</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"args"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">cmd</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">cmd</span> <span class="o">=</span> <span class="n">popenargs</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">raise</span> <span class="n">CalledProcessError</span><span class="p">(</span><span class="n">retcode</span><span class="p">,</span> <span class="n">cmd</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="mi">0</span>
|
|
|
|
|
|
<div class="viewcode-block" id="check_output">
|
|
<a class="viewcode-back" href="../api/evennia.server.evennia_launcher.html#evennia.server.evennia_launcher.check_output">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">check_output</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sa">r</span><span class="sd">"""Run command with arguments and return its output.</span>
|
|
|
|
<span class="sd"> If the exit code was non-zero it raises a CalledProcessError. The</span>
|
|
<span class="sd"> CalledProcessError object will have the return code in the returncode</span>
|
|
<span class="sd"> attribute and output in the output attribute.</span>
|
|
|
|
<span class="sd"> The arguments are the same as for the Popen constructor. Example:</span>
|
|
|
|
<span class="sd"> >>> check_output(["ls", "-l", "/dev/null"])</span>
|
|
<span class="sd"> b'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'</span>
|
|
|
|
<span class="sd"> The stdout argument is not allowed as it is used internally.</span>
|
|
<span class="sd"> To capture standard error in the result, use stderr=STDOUT.</span>
|
|
|
|
<span class="sd"> >>> check_output(["/bin/sh", "-c",</span>
|
|
<span class="sd"> ... "ls -l non_existent_file ; exit 0"],</span>
|
|
<span class="sd"> ... stderr=STDOUT)</span>
|
|
<span class="sd"> b'ls: non_existent_file: No such file or directory\n'</span>
|
|
|
|
<span class="sd"> There is an additional optional argument, "input", allowing you to</span>
|
|
<span class="sd"> pass a string to the subprocess's stdin. If you use this argument</span>
|
|
<span class="sd"> you may not also use the Popen constructor's "stdin" argument, as</span>
|
|
<span class="sd"> it too will be used internally. Example:</span>
|
|
|
|
<span class="sd"> >>> check_output(["sed", "-e", "s/foo/bar/"],</span>
|
|
<span class="sd"> ... input=b"when in the course of fooman events\n")</span>
|
|
<span class="sd"> b'when in the course of barman events\n'</span>
|
|
|
|
<span class="sd"> By default, all communication is in bytes, and therefore any "input"</span>
|
|
<span class="sd"> should be bytes, and the return value will be bytes. If in text mode,</span>
|
|
<span class="sd"> any "input" should be a string, and the return value will be a string</span>
|
|
<span class="sd"> decoded according to locale encoding, or by "encoding" if set. Text mode</span>
|
|
<span class="sd"> is triggered by setting any of text, encoding, errors or universal_newlines.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">for</span> <span class="n">kw</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'stdout'</span><span class="p">,</span> <span class="s1">'check'</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">kw</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s1">'</span><span class="si">{</span><span class="n">kw</span><span class="si">}</span><span class="s1"> argument not allowed, it will be overridden.'</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="s1">'input'</span> <span class="ow">in</span> <span class="n">kwargs</span> <span class="ow">and</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">'input'</span><span class="p">]</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Explicitly passing input=None was previously equivalent to passing an</span>
|
|
<span class="c1"># empty string. That is maintained here for backwards compatibility.</span>
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'universal_newlines'</span><span class="p">)</span> <span class="ow">or</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'text'</span><span class="p">)</span> <span class="ow">or</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'encoding'</span><span class="p">)</span> \
|
|
<span class="ow">or</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'errors'</span><span class="p">):</span>
|
|
<span class="n">empty</span> <span class="o">=</span> <span class="s1">''</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">empty</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">''</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'input'</span><span class="p">]</span> <span class="o">=</span> <span class="n">empty</span>
|
|
|
|
<span class="k">return</span> <span class="n">run</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="n">timeout</span><span class="p">,</span> <span class="n">check</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">)</span><span class="o">.</span><span class="n">stdout</span></div>
|
|
|
|
|
|
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">CompletedProcess</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""A process that has finished running.</span>
|
|
|
|
<span class="sd"> This is returned by run().</span>
|
|
|
|
<span class="sd"> Attributes:</span>
|
|
<span class="sd"> args: The list or str args passed to run().</span>
|
|
<span class="sd"> returncode: The exit code of the process, negative for signals.</span>
|
|
<span class="sd"> stdout: The standard output (None if not captured).</span>
|
|
<span class="sd"> stderr: The standard error (None if not captured).</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">returncode</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="n">args</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">returncode</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">stdout</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">stderr</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'args=</span><span class="si">{!r}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">),</span>
|
|
<span class="s1">'returncode=</span><span class="si">{!r}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="p">)]</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'stdout=</span><span class="si">{!r}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'stderr=</span><span class="si">{!r}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">))</span>
|
|
<span class="k">return</span> <span class="s2">"</span><span class="si">{}</span><span class="s2">(</span><span class="si">{}</span><span class="s2">)"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="s1">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">args</span><span class="p">))</span>
|
|
|
|
<span class="n">__class_getitem__</span> <span class="o">=</span> <span class="nb">classmethod</span><span class="p">(</span><span class="n">types</span><span class="o">.</span><span class="n">GenericAlias</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">check_returncode</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Raise CalledProcessError if the exit code is non-zero."""</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">CalledProcessError</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">run</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span>
|
|
<span class="nb">input</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">capture_output</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">check</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Run command with arguments and return a CompletedProcess instance.</span>
|
|
|
|
<span class="sd"> The returned instance will have attributes args, returncode, stdout and</span>
|
|
<span class="sd"> stderr. By default, stdout and stderr are not captured, and those attributes</span>
|
|
<span class="sd"> will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them,</span>
|
|
<span class="sd"> or pass capture_output=True to capture both.</span>
|
|
|
|
<span class="sd"> If check is True and the exit code was non-zero, it raises a</span>
|
|
<span class="sd"> CalledProcessError. The CalledProcessError object will have the return code</span>
|
|
<span class="sd"> in the returncode attribute, and output & stderr attributes if those streams</span>
|
|
<span class="sd"> were captured.</span>
|
|
|
|
<span class="sd"> If timeout (seconds) is given and the process takes too long,</span>
|
|
<span class="sd"> a TimeoutExpired exception will be raised.</span>
|
|
|
|
<span class="sd"> There is an optional argument "input", allowing you to</span>
|
|
<span class="sd"> pass bytes or a string to the subprocess's stdin. If you use this argument</span>
|
|
<span class="sd"> you may not also use the Popen constructor's "stdin" argument, as</span>
|
|
<span class="sd"> it will be used internally.</span>
|
|
|
|
<span class="sd"> By default, all communication is in bytes, and therefore any "input" should</span>
|
|
<span class="sd"> be bytes, and the stdout and stderr will be bytes. If in text mode, any</span>
|
|
<span class="sd"> "input" should be a string, and stdout and stderr will be strings decoded</span>
|
|
<span class="sd"> according to locale encoding, or by "encoding" if set. Text mode is</span>
|
|
<span class="sd"> triggered by setting any of text, encoding, errors or universal_newlines.</span>
|
|
|
|
<span class="sd"> The other arguments are the same as for the Popen constructor.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'stdin'</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">'stdin and input arguments may not both be used.'</span><span class="p">)</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'stdin'</span><span class="p">]</span> <span class="o">=</span> <span class="n">PIPE</span>
|
|
|
|
<span class="k">if</span> <span class="n">capture_output</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'stdout'</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'stderr'</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s1">'stdout and stderr arguments may not be used '</span>
|
|
<span class="s1">'with capture_output.'</span><span class="p">)</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'stdout'</span><span class="p">]</span> <span class="o">=</span> <span class="n">PIPE</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'stderr'</span><span class="p">]</span> <span class="o">=</span> <span class="n">PIPE</span>
|
|
|
|
<span class="k">with</span> <span class="n">Popen</span><span class="p">(</span><span class="o">*</span><span class="n">popenargs</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span> <span class="k">as</span> <span class="n">process</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">communicate</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="n">timeout</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">TimeoutExpired</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
|
|
<span class="n">process</span><span class="o">.</span><span class="n">kill</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="c1"># Windows accumulates the output in a single blocking</span>
|
|
<span class="c1"># read() call run on child threads, with the timeout</span>
|
|
<span class="c1"># being done in a join() on those threads. communicate()</span>
|
|
<span class="c1"># _after_ kill() is required to collect that and add it</span>
|
|
<span class="c1"># to the exception.</span>
|
|
<span class="n">exc</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="n">exc</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">communicate</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># POSIX _communicate already populated the output so</span>
|
|
<span class="c1"># far into the TimeoutExpired exception.</span>
|
|
<span class="n">process</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
|
|
<span class="k">raise</span>
|
|
<span class="k">except</span><span class="p">:</span> <span class="c1"># Including KeyboardInterrupt, communicate handled that.</span>
|
|
<span class="n">process</span><span class="o">.</span><span class="n">kill</span><span class="p">()</span>
|
|
<span class="c1"># We don't call process.wait() as .__exit__ does that for us.</span>
|
|
<span class="k">raise</span>
|
|
<span class="n">retcode</span> <span class="o">=</span> <span class="n">process</span><span class="o">.</span><span class="n">poll</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">check</span> <span class="ow">and</span> <span class="n">retcode</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">CalledProcessError</span><span class="p">(</span><span class="n">retcode</span><span class="p">,</span> <span class="n">process</span><span class="o">.</span><span class="n">args</span><span class="p">,</span>
|
|
<span class="n">output</span><span class="o">=</span><span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">stderr</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">CompletedProcess</span><span class="p">(</span><span class="n">process</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">retcode</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">list2cmdline</span><span class="p">(</span><span class="n">seq</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""</span>
|
|
<span class="sd"> Translate a sequence of arguments into a command line</span>
|
|
<span class="sd"> string, using the same rules as the MS C runtime:</span>
|
|
|
|
<span class="sd"> 1) Arguments are delimited by white space, which is either a</span>
|
|
<span class="sd"> space or a tab.</span>
|
|
|
|
<span class="sd"> 2) A string surrounded by double quotation marks is</span>
|
|
<span class="sd"> interpreted as a single argument, regardless of white space</span>
|
|
<span class="sd"> contained within. A quoted string can be embedded in an</span>
|
|
<span class="sd"> argument.</span>
|
|
|
|
<span class="sd"> 3) A double quotation mark preceded by a backslash is</span>
|
|
<span class="sd"> interpreted as a literal double quotation mark.</span>
|
|
|
|
<span class="sd"> 4) Backslashes are interpreted literally, unless they</span>
|
|
<span class="sd"> immediately precede a double quotation mark.</span>
|
|
|
|
<span class="sd"> 5) If backslashes immediately precede a double quotation mark,</span>
|
|
<span class="sd"> every pair of backslashes is interpreted as a literal</span>
|
|
<span class="sd"> backslash. If the number of backslashes is odd, the last</span>
|
|
<span class="sd"> backslash escapes the next double quotation mark as</span>
|
|
<span class="sd"> described in rule 3.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="c1"># See</span>
|
|
<span class="c1"># http://msdn.microsoft.com/en-us/library/17w5ykft.aspx</span>
|
|
<span class="c1"># or search http://msdn.microsoft.com for</span>
|
|
<span class="c1"># "Parsing C++ Command-Line Arguments"</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">needquote</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="nb">map</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">fsdecode</span><span class="p">,</span> <span class="n">seq</span><span class="p">):</span>
|
|
<span class="n">bs_buf</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="c1"># Add a space to separate this argument from the others</span>
|
|
<span class="k">if</span> <span class="n">result</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">' '</span><span class="p">)</span>
|
|
|
|
<span class="n">needquote</span> <span class="o">=</span> <span class="p">(</span><span class="s2">" "</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="s2">"</span><span class="se">\t</span><span class="s2">"</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">)</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">arg</span>
|
|
<span class="k">if</span> <span class="n">needquote</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'"'</span><span class="p">)</span>
|
|
|
|
<span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">arg</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">c</span> <span class="o">==</span> <span class="s1">'</span><span class="se">\\</span><span class="s1">'</span><span class="p">:</span>
|
|
<span class="c1"># Don't know if we need to double yet.</span>
|
|
<span class="n">bs_buf</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">c</span> <span class="o">==</span> <span class="s1">'"'</span><span class="p">:</span>
|
|
<span class="c1"># Double backslashes.</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'</span><span class="se">\\</span><span class="s1">'</span> <span class="o">*</span> <span class="nb">len</span><span class="p">(</span><span class="n">bs_buf</span><span class="p">)</span><span class="o">*</span><span class="mi">2</span><span class="p">)</span>
|
|
<span class="n">bs_buf</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'</span><span class="se">\\</span><span class="s1">"'</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Normal char</span>
|
|
<span class="k">if</span> <span class="n">bs_buf</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">bs_buf</span><span class="p">)</span>
|
|
<span class="n">bs_buf</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">c</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Add remaining backslashes, if any.</span>
|
|
<span class="k">if</span> <span class="n">bs_buf</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">bs_buf</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">needquote</span><span class="p">:</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">bs_buf</span><span class="p">)</span>
|
|
<span class="n">result</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s1">'"'</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">result</span><span class="p">)</span>
|
|
|
|
|
|
<span class="c1"># Various tools for executing commands and looking at their output and status.</span>
|
|
<span class="c1">#</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">getstatusoutput</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Return (exitcode, output) of executing cmd in a shell.</span>
|
|
|
|
<span class="sd"> Execute the string 'cmd' in a shell with 'check_output' and</span>
|
|
<span class="sd"> return a 2-tuple (status, output). The locale encoding is used</span>
|
|
<span class="sd"> to decode the output and process newlines.</span>
|
|
|
|
<span class="sd"> A trailing newline is stripped from the output.</span>
|
|
<span class="sd"> The exit status for the command can be interpreted</span>
|
|
<span class="sd"> according to the rules for the function 'wait'. Example:</span>
|
|
|
|
<span class="sd"> >>> import subprocess</span>
|
|
<span class="sd"> >>> subprocess.getstatusoutput('ls /bin/ls')</span>
|
|
<span class="sd"> (0, '/bin/ls')</span>
|
|
<span class="sd"> >>> subprocess.getstatusoutput('cat /bin/junk')</span>
|
|
<span class="sd"> (1, 'cat: /bin/junk: No such file or directory')</span>
|
|
<span class="sd"> >>> subprocess.getstatusoutput('/bin/junk')</span>
|
|
<span class="sd"> (127, 'sh: /bin/junk: not found')</span>
|
|
<span class="sd"> >>> subprocess.getstatusoutput('/bin/kill $$')</span>
|
|
<span class="sd"> (-15, '')</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="n">check_output</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">shell</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="n">STDOUT</span><span class="p">,</span>
|
|
<span class="n">encoding</span><span class="o">=</span><span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)</span>
|
|
<span class="n">exitcode</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="k">except</span> <span class="n">CalledProcessError</span> <span class="k">as</span> <span class="n">ex</span><span class="p">:</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="n">ex</span><span class="o">.</span><span class="n">output</span>
|
|
<span class="n">exitcode</span> <span class="o">=</span> <span class="n">ex</span><span class="o">.</span><span class="n">returncode</span>
|
|
<span class="k">if</span> <span class="n">data</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">:]</span> <span class="o">==</span> <span class="s1">'</span><span class="se">\n</span><span class="s1">'</span><span class="p">:</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
|
|
<span class="k">return</span> <span class="n">exitcode</span><span class="p">,</span> <span class="n">data</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">getoutput</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Return output (stdout or stderr) of executing cmd in a shell.</span>
|
|
|
|
<span class="sd"> Like getstatusoutput(), except the exit status is ignored and the return</span>
|
|
<span class="sd"> value is a string containing the command's output. Example:</span>
|
|
|
|
<span class="sd"> >>> import subprocess</span>
|
|
<span class="sd"> >>> subprocess.getoutput('ls /bin/ls')</span>
|
|
<span class="sd"> '/bin/ls'</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="n">getstatusoutput</span><span class="p">(</span><span class="n">cmd</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)[</span><span class="mi">1</span><span class="p">]</span>
|
|
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_use_posix_spawn</span><span class="p">():</span>
|
|
<span class="w"> </span><span class="sd">"""Check if posix_spawn() can be used for subprocess.</span>
|
|
|
|
<span class="sd"> subprocess requires a posix_spawn() implementation that properly reports</span>
|
|
<span class="sd"> errors to the parent process, & sets errno on the following failures:</span>
|
|
|
|
<span class="sd"> * Process attribute actions failed.</span>
|
|
<span class="sd"> * File actions failed.</span>
|
|
<span class="sd"> * exec() failed.</span>
|
|
|
|
<span class="sd"> Prefer an implementation which can use vfork() in some cases for best</span>
|
|
<span class="sd"> performance.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">_mswindows</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">os</span><span class="p">,</span> <span class="s1">'posix_spawn'</span><span class="p">):</span>
|
|
<span class="c1"># os.posix_spawn() is not available</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
|
|
<span class="k">if</span> <span class="p">((</span><span class="n">_env</span> <span class="o">:=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'_PYTHON_SUBPROCESS_USE_POSIX_SPAWN'</span><span class="p">))</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'0'</span><span class="p">,</span> <span class="s1">'1'</span><span class="p">)):</span>
|
|
<span class="k">return</span> <span class="nb">bool</span><span class="p">(</span><span class="nb">int</span><span class="p">(</span><span class="n">_env</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'darwin'</span><span class="p">,</span> <span class="s1">'sunos5'</span><span class="p">):</span>
|
|
<span class="c1"># posix_spawn() is a syscall on both macOS and Solaris,</span>
|
|
<span class="c1"># and properly reports errors</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
|
|
<span class="c1"># Check libc name and runtime libc version</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">ver</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">confstr</span><span class="p">(</span><span class="s1">'CS_GNU_LIBC_VERSION'</span><span class="p">)</span>
|
|
<span class="c1"># parse 'glibc 2.28' as ('glibc', (2, 28))</span>
|
|
<span class="n">parts</span> <span class="o">=</span> <span class="n">ver</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">maxsplit</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">parts</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">:</span>
|
|
<span class="c1"># reject unknown format</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span>
|
|
<span class="n">libc</span> <span class="o">=</span> <span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="n">version</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">parts</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">'.'</span><span class="p">)))</span>
|
|
|
|
<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">'linux'</span> <span class="ow">and</span> <span class="n">libc</span> <span class="o">==</span> <span class="s1">'glibc'</span> <span class="ow">and</span> <span class="n">version</span> <span class="o">>=</span> <span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">24</span><span class="p">):</span>
|
|
<span class="c1"># glibc 2.24 has a new Linux posix_spawn implementation using vfork</span>
|
|
<span class="c1"># which properly reports errors to the parent process.</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
<span class="c1"># Note: Don't use the implementation in earlier glibc because it doesn't</span>
|
|
<span class="c1"># use vfork (even if glibc 2.26 added a pipe to properly report errors</span>
|
|
<span class="c1"># to the parent process).</span>
|
|
<span class="k">except</span> <span class="p">(</span><span class="ne">AttributeError</span><span class="p">,</span> <span class="ne">ValueError</span><span class="p">,</span> <span class="ne">OSError</span><span class="p">):</span>
|
|
<span class="c1"># os.confstr() or CS_GNU_LIBC_VERSION value not available</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="c1"># By default, assume that posix_spawn() does not properly report errors.</span>
|
|
<span class="k">return</span> <span class="kc">False</span>
|
|
|
|
|
|
<span class="c1"># These are primarily fail-safe knobs for negatives. A True value does not</span>
|
|
<span class="c1"># guarantee the given libc/syscall API will be used.</span>
|
|
<span class="n">_USE_POSIX_SPAWN</span> <span class="o">=</span> <span class="n">_use_posix_spawn</span><span class="p">()</span>
|
|
<span class="n">_USE_VFORK</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">_HAVE_POSIX_SPAWN_CLOSEFROM</span> <span class="o">=</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">os</span><span class="p">,</span> <span class="s1">'POSIX_SPAWN_CLOSEFROM'</span><span class="p">)</span>
|
|
|
|
|
|
<div class="viewcode-block" id="Popen">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen">[docs]</a>
|
|
<span class="k">class</span><span class="w"> </span><span class="nc">Popen</span><span class="p">:</span>
|
|
<span class="w"> </span><span class="sd">""" Execute a child program in a new process.</span>
|
|
|
|
<span class="sd"> For a complete description of the arguments see the Python documentation.</span>
|
|
|
|
<span class="sd"> Arguments:</span>
|
|
<span class="sd"> args: A string, or a sequence of program arguments.</span>
|
|
|
|
<span class="sd"> bufsize: supplied as the buffering argument to the open() function when</span>
|
|
<span class="sd"> creating the stdin/stdout/stderr pipe file objects</span>
|
|
|
|
<span class="sd"> executable: A replacement program to execute.</span>
|
|
|
|
<span class="sd"> stdin, stdout and stderr: These specify the executed programs' standard</span>
|
|
<span class="sd"> input, standard output and standard error file handles, respectively.</span>
|
|
|
|
<span class="sd"> preexec_fn: (POSIX only) An object to be called in the child process</span>
|
|
<span class="sd"> just before the child is executed.</span>
|
|
|
|
<span class="sd"> close_fds: Controls closing or inheriting of file descriptors.</span>
|
|
|
|
<span class="sd"> shell: If true, the command will be executed through the shell.</span>
|
|
|
|
<span class="sd"> cwd: Sets the current directory before the child is executed.</span>
|
|
|
|
<span class="sd"> env: Defines the environment variables for the new process.</span>
|
|
|
|
<span class="sd"> text: If true, decode stdin, stdout and stderr using the given encoding</span>
|
|
<span class="sd"> (if set) or the system default otherwise.</span>
|
|
|
|
<span class="sd"> universal_newlines: Alias of text, provided for backwards compatibility.</span>
|
|
|
|
<span class="sd"> startupinfo and creationflags (Windows only)</span>
|
|
|
|
<span class="sd"> restore_signals (POSIX only)</span>
|
|
|
|
<span class="sd"> start_new_session (POSIX only)</span>
|
|
|
|
<span class="sd"> process_group (POSIX only)</span>
|
|
|
|
<span class="sd"> group (POSIX only)</span>
|
|
|
|
<span class="sd"> extra_groups (POSIX only)</span>
|
|
|
|
<span class="sd"> user (POSIX only)</span>
|
|
|
|
<span class="sd"> umask (POSIX only)</span>
|
|
|
|
<span class="sd"> pass_fds (POSIX only)</span>
|
|
|
|
<span class="sd"> encoding and errors: Text mode encoding and error handling to use for</span>
|
|
<span class="sd"> file objects stdin, stdout and stderr.</span>
|
|
|
|
<span class="sd"> Attributes:</span>
|
|
<span class="sd"> stdin, stdout, stderr, pid, returncode</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">_child_created</span> <span class="o">=</span> <span class="kc">False</span> <span class="c1"># Set here since __del__ checks it</span>
|
|
|
|
<div class="viewcode-block" id="Popen.__init__">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.__init__">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">bufsize</span><span class="o">=-</span><span class="mi">1</span><span class="p">,</span> <span class="n">executable</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">stdin</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">stdout</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">stderr</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">preexec_fn</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">close_fds</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="n">shell</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">cwd</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">universal_newlines</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">startupinfo</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">creationflags</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span>
|
|
<span class="n">restore_signals</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">start_new_session</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">pass_fds</span><span class="o">=</span><span class="p">(),</span> <span class="o">*</span><span class="p">,</span> <span class="n">user</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">group</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">extra_groups</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">encoding</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">umask</span><span class="o">=-</span><span class="mi">1</span><span class="p">,</span> <span class="n">pipesize</span><span class="o">=-</span><span class="mi">1</span><span class="p">,</span>
|
|
<span class="n">process_group</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Create new Popen instance."""</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">_can_fork_exec</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span>
|
|
<span class="n">errno</span><span class="o">.</span><span class="n">ENOTSUP</span><span class="p">,</span> <span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">sys</span><span class="o">.</span><span class="n">platform</span><span class="si">}</span><span class="s2"> does not support processes."</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">_cleanup</span><span class="p">()</span>
|
|
<span class="c1"># Held while anything is calling waitpid before returncode has been</span>
|
|
<span class="c1"># updated to prevent clobbering returncode if wait() or poll() are</span>
|
|
<span class="c1"># called from multiple threads at once. After acquiring the lock,</span>
|
|
<span class="c1"># code must re-check self.returncode to see if another thread just</span>
|
|
<span class="c1"># finished a waitpid() call.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_waitpid_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_input</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_communication_started</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">if</span> <span class="n">bufsize</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">bufsize</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <span class="c1"># Restore default</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">bufsize</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"bufsize must be an integer"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">stdout</span> <span class="ow">is</span> <span class="n">STDOUT</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"STDOUT can only be used for stderr"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">pipesize</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">pipesize</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <span class="c1"># Restore default</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">pipesize</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"pipesize must be an integer"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">preexec_fn</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"preexec_fn is not supported on Windows "</span>
|
|
<span class="s2">"platforms"</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># POSIX</span>
|
|
<span class="k">if</span> <span class="n">pass_fds</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">close_fds</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">"pass_fds overriding close_fds."</span><span class="p">,</span> <span class="ne">RuntimeWarning</span><span class="p">)</span>
|
|
<span class="n">close_fds</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">if</span> <span class="n">startupinfo</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"startupinfo is only supported on Windows "</span>
|
|
<span class="s2">"platforms"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">creationflags</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"creationflags is only supported on Windows "</span>
|
|
<span class="s2">"platforms"</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="n">args</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pid</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">encoding</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">errors</span> <span class="o">=</span> <span class="n">errors</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span> <span class="o">=</span> <span class="n">pipesize</span>
|
|
|
|
<span class="c1"># Validate the combinations of text and universal_newlines</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">text</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">universal_newlines</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="nb">bool</span><span class="p">(</span><span class="n">universal_newlines</span><span class="p">)</span> <span class="o">!=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">text</span><span class="p">)):</span>
|
|
<span class="k">raise</span> <span class="n">SubprocessError</span><span class="p">(</span><span class="s1">'Cannot disambiguate when both text '</span>
|
|
<span class="s1">'and universal_newlines are supplied but '</span>
|
|
<span class="s1">'different. Pass one or the other.'</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span> <span class="o">=</span> <span class="n">encoding</span> <span class="ow">or</span> <span class="n">errors</span> <span class="ow">or</span> <span class="n">text</span> <span class="ow">or</span> <span class="n">universal_newlines</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span> <span class="ow">and</span> <span class="n">encoding</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">encoding</span> <span class="o">=</span> <span class="n">encoding</span> <span class="o">=</span> <span class="n">_text_encoding</span><span class="p">()</span>
|
|
|
|
<span class="c1"># How long to resume waiting on a child after the first ^C.</span>
|
|
<span class="c1"># There is no right value for this. The purpose is to be polite</span>
|
|
<span class="c1"># yet remain good for interactive users trying to exit a tool.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span> <span class="o">=</span> <span class="mf">0.25</span> <span class="c1"># 1/xkcd221.getRandomNumber()</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_closed_child_pipe_fds</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">bufsize</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">line_buffering</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="c1"># Use the default buffer size for the underlying binary streams</span>
|
|
<span class="c1"># since they don't support line buffering.</span>
|
|
<span class="n">bufsize</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">line_buffering</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">if</span> <span class="n">process_group</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">process_group</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <span class="c1"># The internal APIs are int-only</span>
|
|
|
|
<span class="n">gid</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">group</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">os</span><span class="p">,</span> <span class="s1">'setregid'</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"The 'group' parameter is not supported on the "</span>
|
|
<span class="s2">"current platform"</span><span class="p">)</span>
|
|
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">group</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">grp</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"The group parameter cannot be a string "</span>
|
|
<span class="s2">"on systems without the grp module"</span><span class="p">)</span>
|
|
|
|
<span class="n">gid</span> <span class="o">=</span> <span class="n">grp</span><span class="o">.</span><span class="n">getgrnam</span><span class="p">(</span><span class="n">group</span><span class="p">)</span><span class="o">.</span><span class="n">gr_gid</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">group</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">gid</span> <span class="o">=</span> <span class="n">group</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"Group must be a string or an integer, not </span><span class="si">{}</span><span class="s2">"</span>
|
|
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">group</span><span class="p">)))</span>
|
|
|
|
<span class="k">if</span> <span class="n">gid</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Group ID cannot be negative, got </span><span class="si">{</span><span class="n">gid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="n">gids</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">extra_groups</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">os</span><span class="p">,</span> <span class="s1">'setgroups'</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"The 'extra_groups' parameter is not "</span>
|
|
<span class="s2">"supported on the current platform"</span><span class="p">)</span>
|
|
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">extra_groups</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Groups must be a list, not a string"</span><span class="p">)</span>
|
|
|
|
<span class="n">gids</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">extra_group</span> <span class="ow">in</span> <span class="n">extra_groups</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">extra_group</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">grp</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Items in extra_groups cannot be "</span>
|
|
<span class="s2">"strings on systems without the "</span>
|
|
<span class="s2">"grp module"</span><span class="p">)</span>
|
|
|
|
<span class="n">gids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">grp</span><span class="o">.</span><span class="n">getgrnam</span><span class="p">(</span><span class="n">extra_group</span><span class="p">)</span><span class="o">.</span><span class="n">gr_gid</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">extra_group</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">gids</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">extra_group</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"Items in extra_groups must be a string "</span>
|
|
<span class="s2">"or integer, not </span><span class="si">{}</span><span class="s2">"</span>
|
|
<span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">extra_group</span><span class="p">)))</span>
|
|
|
|
<span class="c1"># make sure that the gids are all positive here so we can do less</span>
|
|
<span class="c1"># checking in the C code</span>
|
|
<span class="k">for</span> <span class="n">gid_check</span> <span class="ow">in</span> <span class="n">gids</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">gid_check</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"Group ID cannot be negative, got </span><span class="si">{</span><span class="n">gid_check</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="n">uid</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">user</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">os</span><span class="p">,</span> <span class="s1">'setreuid'</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"The 'user' parameter is not supported on "</span>
|
|
<span class="s2">"the current platform"</span><span class="p">)</span>
|
|
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="kn">import</span><span class="w"> </span><span class="nn">pwd</span>
|
|
<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"The user parameter cannot be a string "</span>
|
|
<span class="s2">"on systems without the pwd module"</span><span class="p">)</span>
|
|
<span class="n">uid</span> <span class="o">=</span> <span class="n">pwd</span><span class="o">.</span><span class="n">getpwnam</span><span class="p">(</span><span class="n">user</span><span class="p">)</span><span class="o">.</span><span class="n">pw_uid</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">uid</span> <span class="o">=</span> <span class="n">user</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">"User must be a string or an integer"</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">uid</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">"User ID cannot be negative, got </span><span class="si">{</span><span class="n">uid</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Input and output objects. The general principle is like</span>
|
|
<span class="c1"># this:</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Parent Child</span>
|
|
<span class="c1"># ------ -----</span>
|
|
<span class="c1"># p2cwrite ---stdin---> p2cread</span>
|
|
<span class="c1"># c2pread <--stdout--- c2pwrite</span>
|
|
<span class="c1"># errread <--stderr--- errwrite</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># On POSIX, the child objects are file descriptors. On</span>
|
|
<span class="c1"># Windows, these are Windows file handles. The parent objects</span>
|
|
<span class="c1"># are file descriptors on both platforms. The parent objects</span>
|
|
<span class="c1"># are -1 when not using PIPEs. The child objects are -1</span>
|
|
<span class="c1"># when not redirecting.</span>
|
|
|
|
<span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_handles</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">)</span>
|
|
|
|
<span class="c1"># From here on, raising exceptions may cause file descriptor leakage</span>
|
|
|
|
<span class="c1"># We wrap OS handles *before* launching the child, otherwise a</span>
|
|
<span class="c1"># quickly terminating child could make our fds unwrappable</span>
|
|
<span class="c1"># (see #8458).</span>
|
|
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">p2cwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">p2cwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">open_osfhandle</span><span class="p">(</span><span class="n">p2cwrite</span><span class="o">.</span><span class="n">Detach</span><span class="p">(),</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">c2pread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">c2pread</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">open_osfhandle</span><span class="p">(</span><span class="n">c2pread</span><span class="o">.</span><span class="n">Detach</span><span class="p">(),</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">errread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">errread</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">open_osfhandle</span><span class="p">(</span><span class="n">errread</span><span class="o">.</span><span class="n">Detach</span><span class="p">(),</span> <span class="mi">0</span><span class="p">)</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">p2cwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">p2cwrite</span><span class="p">,</span> <span class="s1">'wb'</span><span class="p">,</span> <span class="n">bufsize</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">TextIOWrapper</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">,</span> <span class="n">write_through</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="n">line_buffering</span><span class="o">=</span><span class="n">line_buffering</span><span class="p">,</span>
|
|
<span class="n">encoding</span><span class="o">=</span><span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">c2pread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">c2pread</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">,</span> <span class="n">bufsize</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">TextIOWrapper</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span>
|
|
<span class="n">encoding</span><span class="o">=</span><span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">errread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">errread</span><span class="p">,</span> <span class="s1">'rb'</span><span class="p">,</span> <span class="n">bufsize</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">TextIOWrapper</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span>
|
|
<span class="n">encoding</span><span class="o">=</span><span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="o">=</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_execute_child</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">preexec_fn</span><span class="p">,</span> <span class="n">close_fds</span><span class="p">,</span>
|
|
<span class="n">pass_fds</span><span class="p">,</span> <span class="n">cwd</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span>
|
|
<span class="n">startupinfo</span><span class="p">,</span> <span class="n">creationflags</span><span class="p">,</span> <span class="n">shell</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">,</span>
|
|
<span class="n">restore_signals</span><span class="p">,</span>
|
|
<span class="n">gid</span><span class="p">,</span> <span class="n">gids</span><span class="p">,</span> <span class="n">uid</span><span class="p">,</span> <span class="n">umask</span><span class="p">,</span>
|
|
<span class="n">start_new_session</span><span class="p">,</span> <span class="n">process_group</span><span class="p">)</span>
|
|
<span class="k">except</span><span class="p">:</span>
|
|
<span class="c1"># Cleanup if the child failed starting.</span>
|
|
<span class="k">for</span> <span class="n">f</span> <span class="ow">in</span> <span class="nb">filter</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">)):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">f</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
|
|
<span class="k">pass</span> <span class="c1"># Ignore EBADF or other errors.</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_closed_child_pipe_fds</span><span class="p">:</span>
|
|
<span class="n">to_close</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="n">stdin</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">to_close</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p2cread</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">stdout</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">to_close</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">to_close</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">errwrite</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'_devnull'</span><span class="p">):</span>
|
|
<span class="n">to_close</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_devnull</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">to_close</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_mswindows</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">Handle</span><span class="p">):</span>
|
|
<span class="n">fd</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="k">raise</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="n">obj_repr</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"<</span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="o">.</span><span class="vm">__name__</span><span class="si">}</span><span class="s2">: "</span>
|
|
<span class="sa">f</span><span class="s2">"returncode: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">returncode</span><span class="si">}</span><span class="s2"> args: </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="si">!r}</span><span class="s2">>"</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">obj_repr</span><span class="p">)</span> <span class="o">></span> <span class="mi">80</span><span class="p">:</span>
|
|
<span class="n">obj_repr</span> <span class="o">=</span> <span class="n">obj_repr</span><span class="p">[:</span><span class="mi">76</span><span class="p">]</span> <span class="o">+</span> <span class="s2">"...>"</span>
|
|
<span class="k">return</span> <span class="n">obj_repr</span>
|
|
|
|
<span class="n">__class_getitem__</span> <span class="o">=</span> <span class="nb">classmethod</span><span class="p">(</span><span class="n">types</span><span class="o">.</span><span class="n">GenericAlias</span><span class="p">)</span>
|
|
|
|
<span class="nd">@property</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">universal_newlines</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="c1"># universal_newlines as retained as an alias of text_mode for API</span>
|
|
<span class="c1"># compatibility. bpo-31756</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span>
|
|
|
|
<span class="nd">@universal_newlines</span><span class="o">.</span><span class="n">setter</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">universal_newlines</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">universal_newlines</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">universal_newlines</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_translate_newlines</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="p">):</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="n">encoding</span><span class="p">,</span> <span class="n">errors</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">data</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="se">\r\n</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">"</span><span class="se">\r</span><span class="s2">"</span><span class="p">,</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="bp">self</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">value</span><span class="p">,</span> <span class="n">traceback</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">try</span><span class="p">:</span> <span class="c1"># Flushing a BufferedWriter may raise an error</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">exc_type</span> <span class="o">==</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
|
|
<span class="c1"># https://bugs.python.org/issue25942</span>
|
|
<span class="c1"># In the case of a KeyboardInterrupt we assume the SIGINT</span>
|
|
<span class="c1"># was also already sent to our child processes. We can't</span>
|
|
<span class="c1"># block indefinitely as that is not user friendly.</span>
|
|
<span class="c1"># If we have not already waited a brief amount of time in</span>
|
|
<span class="c1"># an interrupted .wait() or .communicate() call, do so here</span>
|
|
<span class="c1"># for consistency.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">TimeoutExpired</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># Note that this has been done.</span>
|
|
<span class="k">return</span> <span class="c1"># resume the KeyboardInterrupt</span>
|
|
|
|
<span class="c1"># Wait for the process to terminate, to avoid zombies.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="fm">__del__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_maxsize</span><span class="o">=</span><span class="n">sys</span><span class="o">.</span><span class="n">maxsize</span><span class="p">,</span> <span class="n">_warn</span><span class="o">=</span><span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_child_created</span><span class="p">:</span>
|
|
<span class="c1"># We didn't get to successfully create a child process.</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Not reading subprocess exit status creates a zombie process which</span>
|
|
<span class="c1"># is only destroyed at the parent python process exit</span>
|
|
<span class="n">_warn</span><span class="p">(</span><span class="s2">"subprocess </span><span class="si">%s</span><span class="s2"> is still running"</span> <span class="o">%</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span>
|
|
<span class="ne">ResourceWarning</span><span class="p">,</span> <span class="n">source</span><span class="o">=</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="c1"># In case the child hasn't been waited on, check if it's done.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_internal_poll</span><span class="p">(</span><span class="n">_deadstate</span><span class="o">=</span><span class="n">_maxsize</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">_active</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Child is still running, keep us alive until we can wait on it.</span>
|
|
<span class="n">_active</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_devnull</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'_devnull'</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_devnull</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">open</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">devnull</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">O_RDWR</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_devnull</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_stdin_write</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">input</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">BrokenPipeError</span><span class="p">:</span>
|
|
<span class="k">pass</span> <span class="c1"># communicate() must ignore broken pipe errors.</span>
|
|
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">exc</span><span class="o">.</span><span class="n">errno</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">EINVAL</span><span class="p">:</span>
|
|
<span class="c1"># bpo-19612, bpo-30418: On Windows, stdin.write() fails</span>
|
|
<span class="c1"># with EINVAL if the child process exited or if the child</span>
|
|
<span class="c1"># process is still running but closed the pipe.</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">BrokenPipeError</span><span class="p">:</span>
|
|
<span class="k">pass</span> <span class="c1"># communicate() must ignore broken pipe errors.</span>
|
|
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">exc</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">exc</span><span class="o">.</span><span class="n">errno</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">EINVAL</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span>
|
|
|
|
<div class="viewcode-block" id="Popen.communicate">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.communicate">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">communicate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Interact with process: Send data to stdin and close it.</span>
|
|
<span class="sd"> Read data from stdout and stderr, until end-of-file is</span>
|
|
<span class="sd"> reached. Wait for process to terminate.</span>
|
|
|
|
<span class="sd"> The optional "input" argument should be data to be sent to the</span>
|
|
<span class="sd"> child process, or None, if no data should be sent to the child.</span>
|
|
<span class="sd"> communicate() returns a tuple (stdout, stderr).</span>
|
|
|
|
<span class="sd"> By default, all communication is in bytes, and therefore any</span>
|
|
<span class="sd"> "input" should be bytes, and the (stdout, stderr) will be bytes.</span>
|
|
<span class="sd"> If in text mode (indicated by self.text_mode), any "input" should</span>
|
|
<span class="sd"> be a string, and (stdout, stderr) will be strings decoded</span>
|
|
<span class="sd"> according to locale encoding, or by "encoding" if set. Text mode</span>
|
|
<span class="sd"> is triggered by setting any of text, encoding, errors or</span>
|
|
<span class="sd"> universal_newlines.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_communication_started</span> <span class="ow">and</span> <span class="nb">input</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Cannot send input after starting communication"</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Optimization: If we are not worried about timeouts, we haven't</span>
|
|
<span class="c1"># started communicating, and we have one or zero pipes, using select()</span>
|
|
<span class="c1"># or threads is unnecessary.</span>
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">timeout</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_communication_started</span> <span class="ow">and</span>
|
|
<span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">]</span><span class="o">.</span><span class="n">count</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span> <span class="o">>=</span> <span class="mi">2</span><span class="p">):</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_stdin_write</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">:</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">:</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">read</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">endtime</span> <span class="o">=</span> <span class="n">_time</span><span class="p">()</span> <span class="o">+</span> <span class="n">timeout</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">endtime</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_communicate</span><span class="p">(</span><span class="nb">input</span><span class="p">,</span> <span class="n">endtime</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
|
|
<span class="c1"># https://bugs.python.org/issue25942</span>
|
|
<span class="c1"># See the detailed comment in .wait().</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">sigint_timeout</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">))</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">sigint_timeout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># nothing else should wait.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="n">sigint_timeout</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">TimeoutExpired</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">raise</span> <span class="c1"># resume the KeyboardInterrupt</span>
|
|
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_communication_started</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="n">sts</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">))</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">)</span></div>
|
|
|
|
|
|
|
|
<div class="viewcode-block" id="Popen.poll">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.poll">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">poll</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Check if child process has terminated. Set and return returncode</span>
|
|
<span class="sd"> attribute."""</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_internal_poll</span><span class="p">()</span></div>
|
|
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_remaining_time</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endtime</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Convenience for _communicate when computing timeouts."""</span>
|
|
<span class="k">if</span> <span class="n">endtime</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">endtime</span> <span class="o">-</span> <span class="n">_time</span><span class="p">()</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_check_timeout</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">endtime</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">,</span> <span class="n">stdout_seq</span><span class="p">,</span> <span class="n">stderr_seq</span><span class="p">,</span>
|
|
<span class="n">skip_check_and_raise</span><span class="o">=</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Convenience for checking if a timeout has expired."""</span>
|
|
<span class="k">if</span> <span class="n">endtime</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="n">skip_check_and_raise</span> <span class="ow">or</span> <span class="n">_time</span><span class="p">()</span> <span class="o">></span> <span class="n">endtime</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">TimeoutExpired</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">,</span>
|
|
<span class="n">output</span><span class="o">=</span><span class="sa">b</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">stdout_seq</span><span class="p">)</span> <span class="k">if</span> <span class="n">stdout_seq</span> <span class="k">else</span> <span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">stderr</span><span class="o">=</span><span class="sa">b</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">stderr_seq</span><span class="p">)</span> <span class="k">if</span> <span class="n">stderr_seq</span> <span class="k">else</span> <span class="kc">None</span><span class="p">)</span>
|
|
|
|
|
|
<div class="viewcode-block" id="Popen.wait">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.wait">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">wait</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">timeout</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Wait for child process to terminate; returns self.returncode."""</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">endtime</span> <span class="o">=</span> <span class="n">_time</span><span class="p">()</span> <span class="o">+</span> <span class="n">timeout</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="n">timeout</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">KeyboardInterrupt</span><span class="p">:</span>
|
|
<span class="c1"># https://bugs.python.org/issue25942</span>
|
|
<span class="c1"># The first keyboard interrupt waits briefly for the child to</span>
|
|
<span class="c1"># exit under the common assumption that it also received the ^C</span>
|
|
<span class="c1"># generated SIGINT and will exit rapidly.</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">sigint_timeout</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">))</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">sigint_timeout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_sigint_wait_secs</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># nothing else should wait.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="n">sigint_timeout</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">TimeoutExpired</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">raise</span> <span class="c1"># resume the KeyboardInterrupt</span></div>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_close_pipe_fds</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">):</span>
|
|
<span class="c1"># self._devnull is not always defined.</span>
|
|
<span class="n">devnull_fd</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'_devnull'</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
|
|
<span class="k">with</span> <span class="n">contextlib</span><span class="o">.</span><span class="n">ExitStack</span><span class="p">()</span> <span class="k">as</span> <span class="n">stack</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">p2cread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">p2cread</span><span class="o">.</span><span class="n">Close</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">c2pwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">c2pwrite</span><span class="o">.</span><span class="n">Close</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">errwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">errwrite</span><span class="o">.</span><span class="n">Close</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">p2cread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">and</span> <span class="n">p2cwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">and</span> <span class="n">p2cread</span> <span class="o">!=</span> <span class="n">devnull_fd</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">,</span> <span class="n">p2cread</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">c2pwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">and</span> <span class="n">c2pread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">and</span> <span class="n">c2pwrite</span> <span class="o">!=</span> <span class="n">devnull_fd</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">errwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">and</span> <span class="n">errread</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">and</span> <span class="n">errwrite</span> <span class="o">!=</span> <span class="n">devnull_fd</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">devnull_fd</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">stack</span><span class="o">.</span><span class="n">callback</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">,</span> <span class="n">devnull_fd</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Prevent a double close of these handles/fds from __init__ on error.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_closed_child_pipe_fds</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="nd">@contextlib</span><span class="o">.</span><span class="n">contextmanager</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_on_error_fd_closer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Helper to ensure file descriptors opened in _get_handles are closed"""</span>
|
|
<span class="n">to_close</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">yield</span> <span class="n">to_close</span>
|
|
<span class="k">except</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s1">'_devnull'</span><span class="p">):</span>
|
|
<span class="n">to_close</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_devnull</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">_devnull</span>
|
|
<span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="n">to_close</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_mswindows</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">fd</span><span class="p">,</span> <span class="n">Handle</span><span class="p">):</span>
|
|
<span class="n">fd</span><span class="o">.</span><span class="n">Close</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">OSError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">raise</span>
|
|
|
|
<span class="k">if</span> <span class="n">_mswindows</span><span class="p">:</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Windows methods</span>
|
|
<span class="c1">#</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_handles</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stdin</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Construct and return tuple with IO objects:</span>
|
|
<span class="sd"> p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">stdin</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">stdout</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">stderr</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
|
|
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
|
|
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_on_error_fd_closer</span><span class="p">()</span> <span class="k">as</span> <span class="n">err_close_fds</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">stdin</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">GetStdHandle</span><span class="p">(</span><span class="n">_winapi</span><span class="o">.</span><span class="n">STD_INPUT_HANDLE</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">p2cread</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreatePipe</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">p2cread</span><span class="p">)</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">p2cread</span><span class="p">)</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">(</span><span class="n">_</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">stdin</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreatePipe</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">p2cread</span><span class="p">),</span> <span class="n">Handle</span><span class="p">(</span><span class="n">p2cwrite</span><span class="p">)</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="n">stdin</span> <span class="o">==</span> <span class="n">DEVNULL</span><span class="p">:</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_devnull</span><span class="p">())</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="n">stdin</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Assuming file-like object</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="n">stdin</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_inheritable</span><span class="p">(</span><span class="n">p2cread</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">stdout</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">GetStdHandle</span><span class="p">(</span><span class="n">_winapi</span><span class="o">.</span><span class="n">STD_OUTPUT_HANDLE</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">c2pwrite</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">_</span><span class="p">,</span> <span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreatePipe</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">)</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">)</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">(</span><span class="n">_</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">stdout</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreatePipe</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">c2pread</span><span class="p">),</span> <span class="n">Handle</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">)</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="n">stdout</span> <span class="o">==</span> <span class="n">DEVNULL</span><span class="p">:</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_devnull</span><span class="p">())</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="n">stdout</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Assuming file-like object</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_inheritable</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">stderr</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">GetStdHandle</span><span class="p">(</span><span class="n">_winapi</span><span class="o">.</span><span class="n">STD_ERROR_HANDLE</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">errwrite</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">_</span><span class="p">,</span> <span class="n">errwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreatePipe</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">errwrite</span><span class="p">)</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">errwrite</span><span class="p">)</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">(</span><span class="n">_</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreatePipe</span><span class="p">(</span><span class="kc">None</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">errread</span><span class="p">),</span> <span class="n">Handle</span><span class="p">(</span><span class="n">errwrite</span><span class="p">)</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">))</span>
|
|
<span class="k">elif</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">STDOUT</span><span class="p">:</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">c2pwrite</span>
|
|
<span class="k">elif</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">DEVNULL</span><span class="p">:</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_get_devnull</span><span class="p">())</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="n">stderr</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Assuming file-like object</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">msvcrt</span><span class="o">.</span><span class="n">get_osfhandle</span><span class="p">(</span><span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">())</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_make_inheritable</span><span class="p">(</span><span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_make_inheritable</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handle</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Return a duplicate of handle, which is inheritable"""</span>
|
|
<span class="n">h</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">DuplicateHandle</span><span class="p">(</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">GetCurrentProcess</span><span class="p">(),</span> <span class="n">handle</span><span class="p">,</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">GetCurrentProcess</span><span class="p">(),</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">DUPLICATE_SAME_ACCESS</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">Handle</span><span class="p">(</span><span class="n">h</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_filter_handle_list</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">handle_list</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Filter out console handles that can't be used</span>
|
|
<span class="sd"> in lpAttributeList["handle_list"] and make sure the list</span>
|
|
<span class="sd"> isn't empty. This also removes duplicate handles."""</span>
|
|
<span class="c1"># An handle with it's lowest two bits set might be a special console</span>
|
|
<span class="c1"># handle that if passed in lpAttributeList["handle_list"], will</span>
|
|
<span class="c1"># cause it to fail.</span>
|
|
<span class="k">return</span> <span class="nb">list</span><span class="p">({</span><span class="n">handle</span> <span class="k">for</span> <span class="n">handle</span> <span class="ow">in</span> <span class="n">handle_list</span>
|
|
<span class="k">if</span> <span class="n">handle</span> <span class="o">&</span> <span class="mh">0x3</span> <span class="o">!=</span> <span class="mh">0x3</span>
|
|
<span class="ow">or</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">GetFileType</span><span class="p">(</span><span class="n">handle</span><span class="p">)</span> <span class="o">!=</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">FILE_TYPE_CHAR</span><span class="p">})</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_execute_child</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">preexec_fn</span><span class="p">,</span> <span class="n">close_fds</span><span class="p">,</span>
|
|
<span class="n">pass_fds</span><span class="p">,</span> <span class="n">cwd</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span>
|
|
<span class="n">startupinfo</span><span class="p">,</span> <span class="n">creationflags</span><span class="p">,</span> <span class="n">shell</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">,</span>
|
|
<span class="n">unused_restore_signals</span><span class="p">,</span>
|
|
<span class="n">unused_gid</span><span class="p">,</span> <span class="n">unused_gids</span><span class="p">,</span> <span class="n">unused_uid</span><span class="p">,</span>
|
|
<span class="n">unused_umask</span><span class="p">,</span>
|
|
<span class="n">unused_start_new_session</span><span class="p">,</span> <span class="n">unused_process_group</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Execute program (MS Windows version)"""</span>
|
|
|
|
<span class="k">assert</span> <span class="ow">not</span> <span class="n">pass_fds</span><span class="p">,</span> <span class="s2">"pass_fds not supported on Windows."</span>
|
|
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">shell</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">'bytes args is not allowed on Windows'</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">list2cmdline</span><span class="p">([</span><span class="n">args</span><span class="p">])</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">PathLike</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">shell</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">'path-like args is not allowed when '</span>
|
|
<span class="s1">'shell is true'</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">list2cmdline</span><span class="p">([</span><span class="n">args</span><span class="p">])</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">list2cmdline</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">executable</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">executable</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fsdecode</span><span class="p">(</span><span class="n">executable</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Process startup details</span>
|
|
<span class="k">if</span> <span class="n">startupinfo</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">startupinfo</span> <span class="o">=</span> <span class="n">STARTUPINFO</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># bpo-34044: Copy STARTUPINFO since it is modified above,</span>
|
|
<span class="c1"># so the caller can reuse it multiple times.</span>
|
|
<span class="n">startupinfo</span> <span class="o">=</span> <span class="n">startupinfo</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
|
|
|
|
<span class="n">use_std_handles</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">not</span> <span class="ow">in</span> <span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">use_std_handles</span><span class="p">:</span>
|
|
<span class="n">startupinfo</span><span class="o">.</span><span class="n">dwFlags</span> <span class="o">|=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">STARTF_USESTDHANDLES</span>
|
|
<span class="n">startupinfo</span><span class="o">.</span><span class="n">hStdInput</span> <span class="o">=</span> <span class="n">p2cread</span>
|
|
<span class="n">startupinfo</span><span class="o">.</span><span class="n">hStdOutput</span> <span class="o">=</span> <span class="n">c2pwrite</span>
|
|
<span class="n">startupinfo</span><span class="o">.</span><span class="n">hStdError</span> <span class="o">=</span> <span class="n">errwrite</span>
|
|
|
|
<span class="n">attribute_list</span> <span class="o">=</span> <span class="n">startupinfo</span><span class="o">.</span><span class="n">lpAttributeList</span>
|
|
<span class="n">have_handle_list</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">attribute_list</span> <span class="ow">and</span>
|
|
<span class="s2">"handle_list"</span> <span class="ow">in</span> <span class="n">attribute_list</span> <span class="ow">and</span>
|
|
<span class="n">attribute_list</span><span class="p">[</span><span class="s2">"handle_list"</span><span class="p">])</span>
|
|
|
|
<span class="c1"># If we were given an handle_list or need to create one</span>
|
|
<span class="k">if</span> <span class="n">have_handle_list</span> <span class="ow">or</span> <span class="p">(</span><span class="n">use_std_handles</span> <span class="ow">and</span> <span class="n">close_fds</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">attribute_list</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">attribute_list</span> <span class="o">=</span> <span class="n">startupinfo</span><span class="o">.</span><span class="n">lpAttributeList</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="n">handle_list</span> <span class="o">=</span> <span class="n">attribute_list</span><span class="p">[</span><span class="s2">"handle_list"</span><span class="p">]</span> <span class="o">=</span> \
|
|
<span class="nb">list</span><span class="p">(</span><span class="n">attribute_list</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"handle_list"</span><span class="p">,</span> <span class="p">[]))</span>
|
|
|
|
<span class="k">if</span> <span class="n">use_std_handles</span><span class="p">:</span>
|
|
<span class="n">handle_list</span> <span class="o">+=</span> <span class="p">[</span><span class="nb">int</span><span class="p">(</span><span class="n">p2cread</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">),</span> <span class="nb">int</span><span class="p">(</span><span class="n">errwrite</span><span class="p">)]</span>
|
|
|
|
<span class="n">handle_list</span><span class="p">[:]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_filter_handle_list</span><span class="p">(</span><span class="n">handle_list</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">handle_list</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">close_fds</span><span class="p">:</span>
|
|
<span class="n">warnings</span><span class="o">.</span><span class="n">warn</span><span class="p">(</span><span class="s2">"startupinfo.lpAttributeList['handle_list'] "</span>
|
|
<span class="s2">"overriding close_fds"</span><span class="p">,</span> <span class="ne">RuntimeWarning</span><span class="p">)</span>
|
|
|
|
<span class="c1"># When using the handle_list we always request to inherit</span>
|
|
<span class="c1"># handles but the only handles that will be inherited are</span>
|
|
<span class="c1"># the ones in the handle_list</span>
|
|
<span class="n">close_fds</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">if</span> <span class="n">shell</span><span class="p">:</span>
|
|
<span class="n">startupinfo</span><span class="o">.</span><span class="n">dwFlags</span> <span class="o">|=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">STARTF_USESHOWWINDOW</span>
|
|
<span class="n">startupinfo</span><span class="o">.</span><span class="n">wShowWindow</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">SW_HIDE</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">executable</span><span class="p">:</span>
|
|
<span class="c1"># gh-101283: without a fully-qualified path, before Windows</span>
|
|
<span class="c1"># checks the system directories, it first looks in the</span>
|
|
<span class="c1"># application directory, and also the current directory if</span>
|
|
<span class="c1"># NeedCurrentDirectoryForExePathW(ExeName) is true, so try</span>
|
|
<span class="c1"># to avoid executing unqualified "cmd.exe".</span>
|
|
<span class="n">comspec</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'ComSpec'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">comspec</span><span class="p">:</span>
|
|
<span class="n">system_root</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'SystemRoot'</span><span class="p">,</span> <span class="s1">''</span><span class="p">)</span>
|
|
<span class="n">comspec</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">system_root</span><span class="p">,</span> <span class="s1">'System32'</span><span class="p">,</span> <span class="s1">'cmd.exe'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isabs</span><span class="p">(</span><span class="n">comspec</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">FileNotFoundError</span><span class="p">(</span><span class="s1">'shell not found: neither %ComSpec% nor %SystemRoot</span><span class="si">% i</span><span class="s1">s set'</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">isabs</span><span class="p">(</span><span class="n">comspec</span><span class="p">):</span>
|
|
<span class="n">executable</span> <span class="o">=</span> <span class="n">comspec</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">comspec</span> <span class="o">=</span> <span class="n">executable</span>
|
|
|
|
<span class="n">args</span> <span class="o">=</span> <span class="s1">'</span><span class="si">{}</span><span class="s1"> /c "</span><span class="si">{}</span><span class="s1">"'</span><span class="o">.</span><span class="n">format</span> <span class="p">(</span><span class="n">comspec</span><span class="p">,</span> <span class="n">args</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">cwd</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">cwd</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fsdecode</span><span class="p">(</span><span class="n">cwd</span><span class="p">)</span>
|
|
|
|
<span class="n">sys</span><span class="o">.</span><span class="n">audit</span><span class="p">(</span><span class="s2">"subprocess.Popen"</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">cwd</span><span class="p">,</span> <span class="n">env</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Start the process</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">hp</span><span class="p">,</span> <span class="n">ht</span><span class="p">,</span> <span class="n">pid</span><span class="p">,</span> <span class="n">tid</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">CreateProcess</span><span class="p">(</span><span class="n">executable</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span>
|
|
<span class="c1"># no special security</span>
|
|
<span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">,</span>
|
|
<span class="nb">int</span><span class="p">(</span><span class="ow">not</span> <span class="n">close_fds</span><span class="p">),</span>
|
|
<span class="n">creationflags</span><span class="p">,</span>
|
|
<span class="n">env</span><span class="p">,</span>
|
|
<span class="n">cwd</span><span class="p">,</span>
|
|
<span class="n">startupinfo</span><span class="p">)</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="c1"># Child is launched. Close the parent's copy of those pipe</span>
|
|
<span class="c1"># handles that only the child should have open. You need</span>
|
|
<span class="c1"># to make sure that no handles to the write end of the</span>
|
|
<span class="c1"># output pipe are maintained in this process or else the</span>
|
|
<span class="c1"># pipe will not close when the child process exits and the</span>
|
|
<span class="c1"># ReadFile will hang.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_close_pipe_fds</span><span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Retain the process handle, but close the thread handle</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_child_created</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_handle</span> <span class="o">=</span> <span class="n">Handle</span><span class="p">(</span><span class="n">hp</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pid</span> <span class="o">=</span> <span class="n">pid</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">CloseHandle</span><span class="p">(</span><span class="n">ht</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_internal_poll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_deadstate</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">_WaitForSingleObject</span><span class="o">=</span><span class="n">_winapi</span><span class="o">.</span><span class="n">WaitForSingleObject</span><span class="p">,</span>
|
|
<span class="n">_WAIT_OBJECT_0</span><span class="o">=</span><span class="n">_winapi</span><span class="o">.</span><span class="n">WAIT_OBJECT_0</span><span class="p">,</span>
|
|
<span class="n">_GetExitCodeProcess</span><span class="o">=</span><span class="n">_winapi</span><span class="o">.</span><span class="n">GetExitCodeProcess</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Check if child process has terminated. Returns returncode</span>
|
|
<span class="sd"> attribute.</span>
|
|
|
|
<span class="sd"> This method is called by __del__, so it can only refer to objects</span>
|
|
<span class="sd"> in its local scope.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_WaitForSingleObject</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">==</span> <span class="n">_WAIT_OBJECT_0</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">_GetExitCodeProcess</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_wait</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">timeout</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Internal implementation of wait() on Windows."""</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">timeout_millis</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">INFINITE</span>
|
|
<span class="k">elif</span> <span class="n">timeout</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="n">timeout_millis</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">timeout_millis</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">timeout</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># API note: Returns immediately if timeout_millis == 0.</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">WaitForSingleObject</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">,</span>
|
|
<span class="n">timeout_millis</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">result</span> <span class="o">==</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">WAIT_TIMEOUT</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">TimeoutExpired</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">GetExitCodeProcess</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_readerthread</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fh</span><span class="p">,</span> <span class="n">buffer</span><span class="p">):</span>
|
|
<span class="n">buffer</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">fh</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
|
|
<span class="n">fh</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_communicate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">,</span> <span class="n">endtime</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">):</span>
|
|
<span class="c1"># Start reader threads feeding into a list hanging off of this</span>
|
|
<span class="c1"># object, unless they've already been started.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_stdout_buff"</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_stdout_buff</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout_thread</span> <span class="o">=</span> \
|
|
<span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_readerthread</span><span class="p">,</span>
|
|
<span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stdout_buff</span><span class="p">))</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout_thread</span><span class="o">.</span><span class="n">daemon</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s2">"_stderr_buff"</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_stderr_buff</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr_thread</span> <span class="o">=</span> \
|
|
<span class="n">threading</span><span class="o">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_readerthread</span><span class="p">,</span>
|
|
<span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stderr_buff</span><span class="p">))</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr_thread</span><span class="o">.</span><span class="n">daemon</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr_thread</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_stdin_write</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Wait for the reader threads, or time out. If we time out, the</span>
|
|
<span class="c1"># threads remain reading and the fds left open in case the user</span>
|
|
<span class="c1"># calls communicate again.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout_thread</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout_thread</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="n">TimeoutExpired</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr_thread</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr_thread</span><span class="o">.</span><span class="n">is_alive</span><span class="p">():</span>
|
|
<span class="k">raise</span> <span class="n">TimeoutExpired</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Collect the output from and close both pipes, now that we know</span>
|
|
<span class="c1"># both have been read successfully.</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">:</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stdout_buff</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">:</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_stderr_buff</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
|
|
<span class="c1"># All data exchanged. Translate lists into strings.</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="n">stdout</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">stdout</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="n">stderr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">if</span> <span class="n">stderr</span> <span class="k">else</span> <span class="kc">None</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">send_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sig</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Send a signal to the process."""</span>
|
|
<span class="c1"># Don't signal a process that we know has already died.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
<span class="k">if</span> <span class="n">sig</span> <span class="o">==</span> <span class="n">signal</span><span class="o">.</span><span class="n">SIGTERM</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">terminate</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="n">sig</span> <span class="o">==</span> <span class="n">signal</span><span class="o">.</span><span class="n">CTRL_C_EVENT</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="n">signal</span><span class="o">.</span><span class="n">CTRL_C_EVENT</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">sig</span> <span class="o">==</span> <span class="n">signal</span><span class="o">.</span><span class="n">CTRL_BREAK_EVENT</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="n">signal</span><span class="o">.</span><span class="n">CTRL_BREAK_EVENT</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"Unsupported signal: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">sig</span><span class="p">))</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">terminate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Terminates the process."""</span>
|
|
<span class="c1"># Don't terminate a process that we know has already died.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">_winapi</span><span class="o">.</span><span class="n">TerminateProcess</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">PermissionError</span><span class="p">:</span>
|
|
<span class="c1"># ERROR_ACCESS_DENIED (winerror 5) is received when the</span>
|
|
<span class="c1"># process already died.</span>
|
|
<span class="n">rc</span> <span class="o">=</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">GetExitCodeProcess</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_handle</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">rc</span> <span class="o">==</span> <span class="n">_winapi</span><span class="o">.</span><span class="n">STILL_ACTIVE</span><span class="p">:</span>
|
|
<span class="k">raise</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">rc</span>
|
|
|
|
<span class="n">kill</span> <span class="o">=</span> <span class="n">terminate</span>
|
|
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># POSIX methods</span>
|
|
<span class="c1">#</span>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_get_handles</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">stdin</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Construct and return tuple with IO objects:</span>
|
|
<span class="sd"> p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span>
|
|
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_on_error_fd_closer</span><span class="p">()</span> <span class="k">as</span> <span class="n">err_close_fds</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">stdin</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">elif</span> <span class="n">stdin</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">pipe</span><span class="p">()</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">fcntl</span><span class="p">,</span> <span class="s2">"F_SETPIPE_SZ"</span><span class="p">):</span>
|
|
<span class="n">fcntl</span><span class="o">.</span><span class="n">fcntl</span><span class="p">(</span><span class="n">p2cwrite</span><span class="p">,</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">F_SETPIPE_SZ</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">stdin</span> <span class="o">==</span> <span class="n">DEVNULL</span><span class="p">:</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_devnull</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stdin</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">stdin</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Assuming file-like object</span>
|
|
<span class="n">p2cread</span> <span class="o">=</span> <span class="n">stdin</span><span class="o">.</span><span class="n">fileno</span><span class="p">()</span>
|
|
|
|
<span class="k">if</span> <span class="n">stdout</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">elif</span> <span class="n">stdout</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">pipe</span><span class="p">()</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">fcntl</span><span class="p">,</span> <span class="s2">"F_SETPIPE_SZ"</span><span class="p">):</span>
|
|
<span class="n">fcntl</span><span class="o">.</span><span class="n">fcntl</span><span class="p">(</span><span class="n">c2pwrite</span><span class="p">,</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">F_SETPIPE_SZ</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">stdout</span> <span class="o">==</span> <span class="n">DEVNULL</span><span class="p">:</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_devnull</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">stdout</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Assuming file-like object</span>
|
|
<span class="n">c2pwrite</span> <span class="o">=</span> <span class="n">stdout</span><span class="o">.</span><span class="n">fileno</span><span class="p">()</span>
|
|
|
|
<span class="k">if</span> <span class="n">stderr</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">elif</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">PIPE</span><span class="p">:</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">pipe</span><span class="p">()</span>
|
|
<span class="n">err_close_fds</span><span class="o">.</span><span class="n">extend</span><span class="p">((</span><span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">fcntl</span><span class="p">,</span> <span class="s2">"F_SETPIPE_SZ"</span><span class="p">):</span>
|
|
<span class="n">fcntl</span><span class="o">.</span><span class="n">fcntl</span><span class="p">(</span><span class="n">errwrite</span><span class="p">,</span> <span class="n">fcntl</span><span class="o">.</span><span class="n">F_SETPIPE_SZ</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">pipesize</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">STDOUT</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">c2pwrite</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">c2pwrite</span>
|
|
<span class="k">else</span><span class="p">:</span> <span class="c1"># child's stdout is not set, use parent's stdout</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">__stdout__</span><span class="o">.</span><span class="n">fileno</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="n">stderr</span> <span class="o">==</span> <span class="n">DEVNULL</span><span class="p">:</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_get_devnull</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="nb">int</span><span class="p">):</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">stderr</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># Assuming file-like object</span>
|
|
<span class="n">errwrite</span> <span class="o">=</span> <span class="n">stderr</span><span class="o">.</span><span class="n">fileno</span><span class="p">()</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_posix_spawn</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">restore_signals</span><span class="p">,</span> <span class="n">close_fds</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Execute program using os.posix_spawn()."""</span>
|
|
<span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">if</span> <span class="n">restore_signals</span><span class="p">:</span>
|
|
<span class="c1"># See _Py_RestoreSignals() in Python/pylifecycle.c</span>
|
|
<span class="n">sigset</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">signame</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'SIGPIPE'</span><span class="p">,</span> <span class="s1">'SIGXFZ'</span><span class="p">,</span> <span class="s1">'SIGXFSZ'</span><span class="p">):</span>
|
|
<span class="n">signum</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">signal</span><span class="p">,</span> <span class="n">signame</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">signum</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">sigset</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">signum</span><span class="p">)</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'setsigdef'</span><span class="p">]</span> <span class="o">=</span> <span class="n">sigset</span>
|
|
|
|
<span class="n">file_actions</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">fd</span> <span class="ow">in</span> <span class="p">(</span><span class="n">p2cwrite</span><span class="p">,</span> <span class="n">c2pread</span><span class="p">,</span> <span class="n">errread</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">fd</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">file_actions</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">os</span><span class="o">.</span><span class="n">POSIX_SPAWN_CLOSE</span><span class="p">,</span> <span class="n">fd</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">fd</span><span class="p">,</span> <span class="n">fd2</span> <span class="ow">in</span> <span class="p">(</span>
|
|
<span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="n">c2pwrite</span><span class="p">,</span> <span class="mi">1</span><span class="p">),</span>
|
|
<span class="p">(</span><span class="n">errwrite</span><span class="p">,</span> <span class="mi">2</span><span class="p">),</span>
|
|
<span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">fd</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">file_actions</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">os</span><span class="o">.</span><span class="n">POSIX_SPAWN_DUP2</span><span class="p">,</span> <span class="n">fd</span><span class="p">,</span> <span class="n">fd2</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="n">close_fds</span><span class="p">:</span>
|
|
<span class="n">file_actions</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">os</span><span class="o">.</span><span class="n">POSIX_SPAWN_CLOSEFROM</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="n">file_actions</span><span class="p">:</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'file_actions'</span><span class="p">]</span> <span class="o">=</span> <span class="n">file_actions</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pid</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">posix_spawn</span><span class="p">(</span><span class="n">executable</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_child_created</span> <span class="o">=</span> <span class="kc">True</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_close_pipe_fds</span><span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_execute_child</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">preexec_fn</span><span class="p">,</span> <span class="n">close_fds</span><span class="p">,</span>
|
|
<span class="n">pass_fds</span><span class="p">,</span> <span class="n">cwd</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span>
|
|
<span class="n">startupinfo</span><span class="p">,</span> <span class="n">creationflags</span><span class="p">,</span> <span class="n">shell</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">,</span>
|
|
<span class="n">restore_signals</span><span class="p">,</span>
|
|
<span class="n">gid</span><span class="p">,</span> <span class="n">gids</span><span class="p">,</span> <span class="n">uid</span><span class="p">,</span> <span class="n">umask</span><span class="p">,</span>
|
|
<span class="n">start_new_session</span><span class="p">,</span> <span class="n">process_group</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Execute program (POSIX version)"""</span>
|
|
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="p">(</span><span class="nb">str</span><span class="p">,</span> <span class="nb">bytes</span><span class="p">)):</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="p">]</span>
|
|
<span class="k">elif</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">os</span><span class="o">.</span><span class="n">PathLike</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">shell</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s1">'path-like args is not allowed when '</span>
|
|
<span class="s1">'shell is true'</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">args</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">shell</span><span class="p">:</span>
|
|
<span class="c1"># On Android the default shell is at '/system/bin/sh'.</span>
|
|
<span class="n">unix_shell</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'/system/bin/sh'</span> <span class="k">if</span>
|
|
<span class="nb">hasattr</span><span class="p">(</span><span class="n">sys</span><span class="p">,</span> <span class="s1">'getandroidapilevel'</span><span class="p">)</span> <span class="k">else</span> <span class="s1">'/bin/sh'</span><span class="p">)</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">unix_shell</span><span class="p">,</span> <span class="s2">"-c"</span><span class="p">]</span> <span class="o">+</span> <span class="n">args</span>
|
|
<span class="k">if</span> <span class="n">executable</span><span class="p">:</span>
|
|
<span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">executable</span>
|
|
|
|
<span class="k">if</span> <span class="n">executable</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">executable</span> <span class="o">=</span> <span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
|
|
<span class="n">sys</span><span class="o">.</span><span class="n">audit</span><span class="p">(</span><span class="s2">"subprocess.Popen"</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="n">cwd</span><span class="p">,</span> <span class="n">env</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="p">(</span><span class="n">_USE_POSIX_SPAWN</span>
|
|
<span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">executable</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="n">preexec_fn</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="p">(</span><span class="ow">not</span> <span class="n">close_fds</span> <span class="ow">or</span> <span class="n">_HAVE_POSIX_SPAWN_CLOSEFROM</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="ow">not</span> <span class="n">pass_fds</span>
|
|
<span class="ow">and</span> <span class="n">cwd</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="p">(</span><span class="n">p2cread</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="n">p2cread</span> <span class="o">></span> <span class="mi">2</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="p">(</span><span class="n">c2pwrite</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="n">c2pwrite</span> <span class="o">></span> <span class="mi">2</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="p">(</span><span class="n">errwrite</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="n">errwrite</span> <span class="o">></span> <span class="mi">2</span><span class="p">)</span>
|
|
<span class="ow">and</span> <span class="ow">not</span> <span class="n">start_new_session</span>
|
|
<span class="ow">and</span> <span class="n">process_group</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="ow">and</span> <span class="n">gid</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="n">gids</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="n">uid</span> <span class="ow">is</span> <span class="kc">None</span>
|
|
<span class="ow">and</span> <span class="n">umask</span> <span class="o"><</span> <span class="mi">0</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_posix_spawn</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">executable</span><span class="p">,</span> <span class="n">env</span><span class="p">,</span> <span class="n">restore_signals</span><span class="p">,</span> <span class="n">close_fds</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">orig_executable</span> <span class="o">=</span> <span class="n">executable</span>
|
|
|
|
<span class="c1"># For transferring possible exec failure from child to parent.</span>
|
|
<span class="c1"># Data format: "exception name:hex errno:description"</span>
|
|
<span class="c1"># Pickle is not used; it is complex and involves memory allocation.</span>
|
|
<span class="n">errpipe_read</span><span class="p">,</span> <span class="n">errpipe_write</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">pipe</span><span class="p">()</span>
|
|
<span class="c1"># errpipe_write must not be in the standard io 0, 1, or 2 fd range.</span>
|
|
<span class="n">low_fds_to_close</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">while</span> <span class="n">errpipe_write</span> <span class="o"><</span> <span class="mi">3</span><span class="p">:</span>
|
|
<span class="n">low_fds_to_close</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">errpipe_write</span><span class="p">)</span>
|
|
<span class="n">errpipe_write</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">dup</span><span class="p">(</span><span class="n">errpipe_write</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">low_fd</span> <span class="ow">in</span> <span class="n">low_fds_to_close</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">low_fd</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># We must avoid complex work that could involve</span>
|
|
<span class="c1"># malloc or free in the child process to avoid</span>
|
|
<span class="c1"># potential deadlocks, thus we do all this here.</span>
|
|
<span class="c1"># and pass it to fork_exec()</span>
|
|
|
|
<span class="k">if</span> <span class="n">env</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">env_list</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">env</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="n">k</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="sa">b</span><span class="s1">'='</span> <span class="ow">in</span> <span class="n">k</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">"illegal environment variable name"</span><span class="p">)</span>
|
|
<span class="n">env_list</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">k</span> <span class="o">+</span> <span class="sa">b</span><span class="s1">'='</span> <span class="o">+</span> <span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="n">v</span><span class="p">))</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">env_list</span> <span class="o">=</span> <span class="kc">None</span> <span class="c1"># Use execv instead of execve.</span>
|
|
<span class="n">executable</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="n">executable</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">executable</span><span class="p">):</span>
|
|
<span class="n">executable_list</span> <span class="o">=</span> <span class="p">(</span><span class="n">executable</span><span class="p">,)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># This matches the behavior of os._execvpe().</span>
|
|
<span class="n">executable_list</span> <span class="o">=</span> <span class="nb">tuple</span><span class="p">(</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">fsencode</span><span class="p">(</span><span class="nb">dir</span><span class="p">),</span> <span class="n">executable</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="nb">dir</span> <span class="ow">in</span> <span class="n">os</span><span class="o">.</span><span class="n">get_exec_path</span><span class="p">(</span><span class="n">env</span><span class="p">))</span>
|
|
<span class="n">fds_to_keep</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span><span class="n">pass_fds</span><span class="p">)</span>
|
|
<span class="n">fds_to_keep</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">errpipe_write</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">pid</span> <span class="o">=</span> <span class="n">_fork_exec</span><span class="p">(</span>
|
|
<span class="n">args</span><span class="p">,</span> <span class="n">executable_list</span><span class="p">,</span>
|
|
<span class="n">close_fds</span><span class="p">,</span> <span class="nb">tuple</span><span class="p">(</span><span class="nb">sorted</span><span class="p">(</span><span class="nb">map</span><span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="n">fds_to_keep</span><span class="p">))),</span>
|
|
<span class="n">cwd</span><span class="p">,</span> <span class="n">env_list</span><span class="p">,</span>
|
|
<span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span> <span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">,</span>
|
|
<span class="n">errpipe_read</span><span class="p">,</span> <span class="n">errpipe_write</span><span class="p">,</span>
|
|
<span class="n">restore_signals</span><span class="p">,</span> <span class="n">start_new_session</span><span class="p">,</span>
|
|
<span class="n">process_group</span><span class="p">,</span> <span class="n">gid</span><span class="p">,</span> <span class="n">gids</span><span class="p">,</span> <span class="n">uid</span><span class="p">,</span> <span class="n">umask</span><span class="p">,</span>
|
|
<span class="n">preexec_fn</span><span class="p">,</span> <span class="n">_USE_VFORK</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_child_created</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="c1"># be sure the FD is closed no matter what</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">errpipe_write</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_close_pipe_fds</span><span class="p">(</span><span class="n">p2cread</span><span class="p">,</span> <span class="n">p2cwrite</span><span class="p">,</span>
|
|
<span class="n">c2pread</span><span class="p">,</span> <span class="n">c2pwrite</span><span class="p">,</span>
|
|
<span class="n">errread</span><span class="p">,</span> <span class="n">errwrite</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Wait for exec to fail or succeed; possibly raising an</span>
|
|
<span class="c1"># exception (limited in size)</span>
|
|
<span class="n">errpipe_data</span> <span class="o">=</span> <span class="nb">bytearray</span><span class="p">()</span>
|
|
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="n">part</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">errpipe_read</span><span class="p">,</span> <span class="mi">50000</span><span class="p">)</span>
|
|
<span class="n">errpipe_data</span> <span class="o">+=</span> <span class="n">part</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">part</span> <span class="ow">or</span> <span class="nb">len</span><span class="p">(</span><span class="n">errpipe_data</span><span class="p">)</span> <span class="o">></span> <span class="mi">50000</span><span class="p">:</span>
|
|
<span class="k">break</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="c1"># be sure the FD is closed no matter what</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">close</span><span class="p">(</span><span class="n">errpipe_read</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">errpipe_data</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">pid</span><span class="p">,</span> <span class="n">sts</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">waitpid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_handle_exitstatus</span><span class="p">(</span><span class="n">sts</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">sys</span><span class="o">.</span><span class="n">maxsize</span>
|
|
<span class="k">except</span> <span class="ne">ChildProcessError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">exception_name</span><span class="p">,</span> <span class="n">hex_errno</span><span class="p">,</span> <span class="n">err_msg</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">errpipe_data</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="sa">b</span><span class="s1">':'</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>
|
|
<span class="c1"># The encoding here should match the encoding</span>
|
|
<span class="c1"># written in by the subprocess implementations</span>
|
|
<span class="c1"># like _posixsubprocess</span>
|
|
<span class="n">err_msg</span> <span class="o">=</span> <span class="n">err_msg</span><span class="o">.</span><span class="n">decode</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="n">exception_name</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">'SubprocessError'</span>
|
|
<span class="n">hex_errno</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">'0'</span>
|
|
<span class="n">err_msg</span> <span class="o">=</span> <span class="s1">'Bad exception data from child: </span><span class="si">{!r}</span><span class="s1">'</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
|
|
<span class="nb">bytes</span><span class="p">(</span><span class="n">errpipe_data</span><span class="p">))</span>
|
|
<span class="n">child_exception_type</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span>
|
|
<span class="n">builtins</span><span class="p">,</span> <span class="n">exception_name</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">'ascii'</span><span class="p">),</span>
|
|
<span class="n">SubprocessError</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">child_exception_type</span><span class="p">,</span> <span class="ne">OSError</span><span class="p">)</span> <span class="ow">and</span> <span class="n">hex_errno</span><span class="p">:</span>
|
|
<span class="n">errno_num</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">hex_errno</span><span class="p">,</span> <span class="mi">16</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">err_msg</span> <span class="o">==</span> <span class="s2">"noexec:chdir"</span><span class="p">:</span>
|
|
<span class="n">err_msg</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="c1"># The error must be from chdir(cwd).</span>
|
|
<span class="n">err_filename</span> <span class="o">=</span> <span class="n">cwd</span>
|
|
<span class="k">elif</span> <span class="n">err_msg</span> <span class="o">==</span> <span class="s2">"noexec"</span><span class="p">:</span>
|
|
<span class="n">err_msg</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="n">err_filename</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">err_filename</span> <span class="o">=</span> <span class="n">orig_executable</span>
|
|
<span class="k">if</span> <span class="n">errno_num</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="n">err_msg</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">strerror</span><span class="p">(</span><span class="n">errno_num</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">err_filename</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">child_exception_type</span><span class="p">(</span><span class="n">errno_num</span><span class="p">,</span> <span class="n">err_msg</span><span class="p">,</span> <span class="n">err_filename</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">child_exception_type</span><span class="p">(</span><span class="n">errno_num</span><span class="p">,</span> <span class="n">err_msg</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="n">child_exception_type</span><span class="p">(</span><span class="n">err_msg</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_handle_exitstatus</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sts</span><span class="p">,</span> <span class="n">_del_safe</span><span class="o">=</span><span class="n">_del_safe</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""All callers to this function MUST hold self._waitpid_lock."""</span>
|
|
<span class="c1"># This method is called (indirectly) by __del__, so it cannot</span>
|
|
<span class="c1"># refer to anything outside of its local scope.</span>
|
|
<span class="k">if</span> <span class="n">_del_safe</span><span class="o">.</span><span class="n">WIFSTOPPED</span><span class="p">(</span><span class="n">sts</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="o">-</span><span class="n">_del_safe</span><span class="o">.</span><span class="n">WSTOPSIG</span><span class="p">(</span><span class="n">sts</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">_del_safe</span><span class="o">.</span><span class="n">waitstatus_to_exitcode</span><span class="p">(</span><span class="n">sts</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_internal_poll</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">_deadstate</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">_del_safe</span><span class="o">=</span><span class="n">_del_safe</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Check if child process has terminated. Returns returncode</span>
|
|
<span class="sd"> attribute.</span>
|
|
|
|
<span class="sd"> This method is called by __del__, so it cannot reference anything</span>
|
|
<span class="sd"> outside of the local scope (nor can any methods it calls).</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_waitpid_lock</span><span class="o">.</span><span class="n">acquire</span><span class="p">(</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="c1"># Something else is busy calling waitpid. Don't allow two</span>
|
|
<span class="c1"># at once. We know nothing yet.</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="c1"># Another thread waited.</span>
|
|
<span class="n">pid</span><span class="p">,</span> <span class="n">sts</span> <span class="o">=</span> <span class="n">_del_safe</span><span class="o">.</span><span class="n">waitpid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="n">_del_safe</span><span class="o">.</span><span class="n">WNOHANG</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_handle_exitstatus</span><span class="p">(</span><span class="n">sts</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">OSError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_deadstate</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="n">_deadstate</span>
|
|
<span class="k">elif</span> <span class="n">e</span><span class="o">.</span><span class="n">errno</span> <span class="o">==</span> <span class="n">_del_safe</span><span class="o">.</span><span class="n">ECHILD</span><span class="p">:</span>
|
|
<span class="c1"># This happens if SIGCLD is set to be ignored or</span>
|
|
<span class="c1"># waiting for child processes has otherwise been</span>
|
|
<span class="c1"># disabled for our process. This child is dead, we</span>
|
|
<span class="c1"># can't get the status.</span>
|
|
<span class="c1"># http://bugs.python.org/issue15756</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_waitpid_lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_try_wait</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">wait_flags</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""All callers to this function MUST hold self._waitpid_lock."""</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">sts</span><span class="p">)</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">waitpid</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="n">wait_flags</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ChildProcessError</span><span class="p">:</span>
|
|
<span class="c1"># This happens if SIGCLD is set to be ignored or waiting</span>
|
|
<span class="c1"># for child processes has otherwise been disabled for our</span>
|
|
<span class="c1"># process. This child is dead, we can't get the status.</span>
|
|
<span class="n">pid</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span>
|
|
<span class="n">sts</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">sts</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_wait</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">timeout</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Internal implementation of wait() on POSIX."""</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span>
|
|
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">endtime</span> <span class="o">=</span> <span class="n">_time</span><span class="p">()</span> <span class="o">+</span> <span class="n">timeout</span>
|
|
<span class="c1"># Enter a busy loop if we have a timeout. This busy loop was</span>
|
|
<span class="c1"># cribbed from Lib/threading.py in Thread.wait() at r71065.</span>
|
|
<span class="n">delay</span> <span class="o">=</span> <span class="mf">0.0005</span> <span class="c1"># 500 us -> initial delay of 1 ms</span>
|
|
<span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_waitpid_lock</span><span class="o">.</span><span class="n">acquire</span><span class="p">(</span><span class="kc">False</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">break</span> <span class="c1"># Another thread waited.</span>
|
|
<span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">sts</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_try_wait</span><span class="p">(</span><span class="n">os</span><span class="o">.</span><span class="n">WNOHANG</span><span class="p">)</span>
|
|
<span class="k">assert</span> <span class="n">pid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span> <span class="ow">or</span> <span class="n">pid</span> <span class="o">==</span> <span class="mi">0</span>
|
|
<span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_handle_exitstatus</span><span class="p">(</span><span class="n">sts</span><span class="p">)</span>
|
|
<span class="k">break</span>
|
|
<span class="k">finally</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_waitpid_lock</span><span class="o">.</span><span class="n">release</span><span class="p">()</span>
|
|
<span class="n">remaining</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">remaining</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">TimeoutExpired</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="p">,</span> <span class="n">timeout</span><span class="p">)</span>
|
|
<span class="n">delay</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">delay</span> <span class="o">*</span> <span class="mi">2</span><span class="p">,</span> <span class="n">remaining</span><span class="p">,</span> <span class="mf">.05</span><span class="p">)</span>
|
|
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="n">delay</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">while</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">_waitpid_lock</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">break</span> <span class="c1"># Another thread waited.</span>
|
|
<span class="p">(</span><span class="n">pid</span><span class="p">,</span> <span class="n">sts</span><span class="p">)</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_try_wait</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
|
|
<span class="c1"># Check the pid and loop as waitpid has been known to</span>
|
|
<span class="c1"># return 0 even without WNOHANG in odd situations.</span>
|
|
<span class="c1"># http://bugs.python.org/issue14396.</span>
|
|
<span class="k">if</span> <span class="n">pid</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_handle_exitstatus</span><span class="p">(</span><span class="n">sts</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_communicate</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">,</span> <span class="n">endtime</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_communication_started</span><span class="p">:</span>
|
|
<span class="c1"># Flush stdio buffer. This might block, if the user has</span>
|
|
<span class="c1"># been writing to .stdin in an uncontrolled fashion.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">flush</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">BrokenPipeError</span><span class="p">:</span>
|
|
<span class="k">pass</span> <span class="c1"># communicate() must ignore BrokenPipeError.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">input</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">BrokenPipeError</span><span class="p">:</span>
|
|
<span class="k">pass</span> <span class="c1"># communicate() must ignore BrokenPipeError.</span>
|
|
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># Only create this mapping if we haven't already.</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_communication_started</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_fileobj2output</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_fileobj2output</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_fileobj2output</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">]</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">:</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fileobj2output</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">:</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_fileobj2output</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">]</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_save_input</span><span class="p">(</span><span class="nb">input</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input</span><span class="p">:</span>
|
|
<span class="n">input_view</span> <span class="o">=</span> <span class="nb">memoryview</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_input</span><span class="p">)</span>
|
|
|
|
<span class="k">with</span> <span class="n">_PopenSelector</span><span class="p">()</span> <span class="k">as</span> <span class="n">selector</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span> <span class="ow">and</span> <span class="nb">input</span><span class="p">:</span>
|
|
<span class="n">selector</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_WRITE</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">closed</span><span class="p">:</span>
|
|
<span class="n">selector</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_READ</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">closed</span><span class="p">:</span>
|
|
<span class="n">selector</span><span class="o">.</span><span class="n">register</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">,</span> <span class="n">selectors</span><span class="o">.</span><span class="n">EVENT_READ</span><span class="p">)</span>
|
|
|
|
<span class="k">while</span> <span class="n">selector</span><span class="o">.</span><span class="n">get_map</span><span class="p">():</span>
|
|
<span class="n">timeout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">timeout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="n">timeout</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_check_timeout</span><span class="p">(</span><span class="n">endtime</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">,</span>
|
|
<span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">,</span>
|
|
<span class="n">skip_check_and_raise</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span> <span class="c1"># Impossible :)</span>
|
|
<span class="s1">'_check_timeout(..., skip_check_and_raise=True) '</span>
|
|
<span class="s1">'failed to raise TimeoutExpired.'</span><span class="p">)</span>
|
|
|
|
<span class="n">ready</span> <span class="o">=</span> <span class="n">selector</span><span class="o">.</span><span class="n">select</span><span class="p">(</span><span class="n">timeout</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_check_timeout</span><span class="p">(</span><span class="n">endtime</span><span class="p">,</span> <span class="n">orig_timeout</span><span class="p">,</span> <span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">)</span>
|
|
|
|
<span class="c1"># XXX Rewrite these to use non-blocking I/O on the file</span>
|
|
<span class="c1"># objects; they are no longer using C stdio!</span>
|
|
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">events</span> <span class="ow">in</span> <span class="n">ready</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">key</span><span class="o">.</span><span class="n">fileobj</span> <span class="ow">is</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="p">:</span>
|
|
<span class="n">chunk</span> <span class="o">=</span> <span class="n">input_view</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">_input_offset</span> <span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_input_offset</span> <span class="o">+</span> <span class="n">_PIPE_BUF</span><span class="p">]</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_input_offset</span> <span class="o">+=</span> <span class="n">os</span><span class="o">.</span><span class="n">write</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fd</span><span class="p">,</span> <span class="n">chunk</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">BrokenPipeError</span><span class="p">:</span>
|
|
<span class="n">selector</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="p">)</span>
|
|
<span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input_offset</span> <span class="o">>=</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_input</span><span class="p">):</span>
|
|
<span class="n">selector</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="p">)</span>
|
|
<span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="n">key</span><span class="o">.</span><span class="n">fileobj</span> <span class="ow">in</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="p">):</span>
|
|
<span class="n">data</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">read</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fd</span><span class="p">,</span> <span class="mi">32768</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span>
|
|
<span class="n">selector</span><span class="o">.</span><span class="n">unregister</span><span class="p">(</span><span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="p">)</span>
|
|
<span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_fileobj2output</span><span class="p">[</span><span class="n">key</span><span class="o">.</span><span class="n">fileobj</span><span class="p">]</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">wait</span><span class="p">(</span><span class="n">timeout</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_remaining_time</span><span class="p">(</span><span class="n">endtime</span><span class="p">))</span>
|
|
|
|
<span class="c1"># All data exchanged. Translate lists into strings.</span>
|
|
<span class="k">if</span> <span class="n">stdout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">stdout</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">stderr</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="sa">b</span><span class="s1">''</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">stderr</span><span class="p">)</span>
|
|
|
|
<span class="c1"># Translate newlines, if requested.</span>
|
|
<span class="c1"># This also turns bytes into strings.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">stdout</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">stdout</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_translate_newlines</span><span class="p">(</span><span class="n">stdout</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">encoding</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">errors</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">stderr</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="n">stderr</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_translate_newlines</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">encoding</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stderr</span><span class="o">.</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="p">(</span><span class="n">stdout</span><span class="p">,</span> <span class="n">stderr</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">_save_input</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">input</span><span class="p">):</span>
|
|
<span class="c1"># This method is called from the _communicate_with_*() methods</span>
|
|
<span class="c1"># so that if we time out while communicating, we can continue</span>
|
|
<span class="c1"># sending input if we retry.</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">stdin</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_input_offset</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_input</span> <span class="o">=</span> <span class="nb">input</span>
|
|
<span class="k">if</span> <span class="nb">input</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">text_mode</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_input</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_input</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">encoding</span><span class="p">,</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">stdin</span><span class="o">.</span><span class="n">errors</span><span class="p">)</span>
|
|
|
|
|
|
<div class="viewcode-block" id="Popen.send_signal">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.send_signal">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">send_signal</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sig</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Send a signal to the process."""</span>
|
|
<span class="c1"># bpo-38630: Polling reduces the risk of sending a signal to the</span>
|
|
<span class="c1"># wrong process if the process completed, the Popen.returncode</span>
|
|
<span class="c1"># attribute is still None, and the pid has been reassigned</span>
|
|
<span class="c1"># (recycled) to a new different process. This race condition can</span>
|
|
<span class="c1"># happens in two cases.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Case 1. Thread A calls Popen.poll(), thread B calls</span>
|
|
<span class="c1"># Popen.send_signal(). In thread A, waitpid() succeed and returns</span>
|
|
<span class="c1"># the exit status. Thread B calls kill() because poll() in thread A</span>
|
|
<span class="c1"># did not set returncode yet. Calling poll() in thread B prevents</span>
|
|
<span class="c1"># the race condition thanks to Popen._waitpid_lock.</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Case 2. waitpid(pid, 0) has been called directly, without</span>
|
|
<span class="c1"># using Popen methods: returncode is still None is this case.</span>
|
|
<span class="c1"># Calling Popen.poll() will set returncode to a default value,</span>
|
|
<span class="c1"># since waitpid() fails with ProcessLookupError.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">poll</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">returncode</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="c1"># Skip signalling a process that we know has already died.</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="c1"># The race condition can still happen if the race condition</span>
|
|
<span class="c1"># described above happens between the returncode test</span>
|
|
<span class="c1"># and the kill() call.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">os</span><span class="o">.</span><span class="n">kill</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">pid</span><span class="p">,</span> <span class="n">sig</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ProcessLookupError</span><span class="p">:</span>
|
|
<span class="c1"># Suppress the race condition error; bpo-40550.</span>
|
|
<span class="k">pass</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Popen.terminate">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.terminate">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">terminate</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Terminate the process with SIGTERM</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">send_signal</span><span class="p">(</span><span class="n">signal</span><span class="o">.</span><span class="n">SIGTERM</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="Popen.kill">
|
|
<a class="viewcode-back" href="../api/evennia.server.portal.amp_server.html#evennia.server.evennia_launcher.Popen.kill">[docs]</a>
|
|
<span class="k">def</span><span class="w"> </span><span class="nf">kill</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="w"> </span><span class="sd">"""Kill the process with SIGKILL</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">send_signal</span><span class="p">(</span><span class="n">signal</span><span class="o">.</span><span class="n">SIGKILL</span><span class="p">)</span></div>
|
|
</div>
|
|
|
|
</pre></div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../genindex.html" title="General Index"
|
|
>index</a></li>
|
|
<li class="right" >
|
|
<a href="../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../index.html">Evennia latest</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="index.html" >Module code</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">subprocess</a></li>
|
|
</ul>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="footer" role="contentinfo">
|
|
© Copyright 2024, The Evennia developer community.
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 8.2.3.
|
|
</div>
|
|
</body>
|
|
</html> |