| 1 | <!DOCTYPE html>\r |
| 2 | <html lang="en">\r |
| 3 | <head>\r |
| 4 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\r |
| 5 | <meta name="generator" content="AsciiDoc 8.6.9">\r |
| 6 | <title>MLtonProcess</title>\r |
| 7 | <link rel="stylesheet" href="./asciidoc.css" type="text/css">\r |
| 8 | <link rel="stylesheet" href="./pygments.css" type="text/css">\r |
| 9 | \r |
| 10 | \r |
| 11 | <script type="text/javascript" src="./asciidoc.js"></script>\r |
| 12 | <script type="text/javascript">\r |
| 13 | /*<![CDATA[*/\r |
| 14 | asciidoc.install();\r |
| 15 | /*]]>*/\r |
| 16 | </script>\r |
| 17 | <link rel="stylesheet" href="./mlton.css" type="text/css">\r |
| 18 | </head>\r |
| 19 | <body class="article">\r |
| 20 | <div id="banner">\r |
| 21 | <div id="banner-home">\r |
| 22 | <a href="./Home">MLton 20180207</a>\r |
| 23 | </div>\r |
| 24 | </div>\r |
| 25 | <div id="header">\r |
| 26 | <h1>MLtonProcess</h1>\r |
| 27 | </div>\r |
| 28 | <div id="content">\r |
| 29 | <div id="preamble">\r |
| 30 | <div class="sectionbody">\r |
| 31 | <div class="listingblock">\r |
| 32 | <div class="content"><div class="highlight"><pre><span class="k">signature</span><span class="w"> </span><span class="n">MLTON_PROCESS</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r |
| 33 | <span class="w"> </span><span class="k">sig</span><span class="w"></span>\r |
| 34 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">pid</span><span class="w"></span>\r |
| 35 | \r |
| 36 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">spawn</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="n">args</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">list</span><span class="p">,</span><span class="w"> </span><span class="n">path</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="p">}</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">pid</span><span class="w"></span>\r |
| 37 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">spawne</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="n">args</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">list</span><span class="p">,</span><span class="w"> </span><span class="n">env</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">list</span><span class="p">,</span><span class="w"> </span><span class="n">path</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="p">}</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">pid</span><span class="w"></span>\r |
| 38 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">spawnp</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="n">args</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">list</span><span class="p">,</span><span class="w"> </span><span class="n">file</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="p">}</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">pid</span><span class="w"></span>\r |
| 39 | \r |
| 40 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 41 | \r |
| 42 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">input</span><span class="w"></span>\r |
| 43 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">output</span><span class="w"></span>\r |
| 44 | \r |
| 45 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">none</span><span class="w"></span>\r |
| 46 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">chain</span><span class="w"></span>\r |
| 47 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="n">any</span><span class="w"></span>\r |
| 48 | \r |
| 49 | <span class="w"> </span><span class="k">exception</span><span class="w"> </span><span class="n">MisuseOfForget</span><span class="w"></span>\r |
| 50 | <span class="w"> </span><span class="k">exception</span><span class="w"> </span><span class="n">DoublyRedirected</span><span class="w"></span>\r |
| 51 | \r |
| 52 | <span class="w"> </span><span class="k">structure</span><span class="w"> </span><span class="n">Child</span><span class="p">:</span><span class="w"></span>\r |
| 53 | <span class="w"> </span><span class="k">sig</span><span class="w"></span>\r |
| 54 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="p">(</span><span class="n">'use</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 55 | \r |
| 56 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">binIn</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">BinIO</span><span class="p">.</span><span class="n">instream</span><span class="p">,</span><span class="w"> </span><span class="n">input</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">BinIO</span><span class="p">.</span><span class="n">instream</span><span class="w"></span>\r |
| 57 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">binOut</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">BinIO</span><span class="p">.</span><span class="n">outstream</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">BinIO</span><span class="p">.</span><span class="n">outstream</span><span class="w"></span>\r |
| 58 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">fd</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">Posix</span><span class="p">.</span><span class="n">FileSys</span><span class="p">.</span><span class="n">file_desc</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">Posix</span><span class="p">.</span><span class="n">FileSys</span><span class="p">.</span><span class="n">file_desc</span><span class="w"></span>\r |
| 59 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">remember</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">any</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">'use</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 60 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">textIn</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">TextIO</span><span class="p">.</span><span class="n">instream</span><span class="p">,</span><span class="w"> </span><span class="n">input</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">TextIO</span><span class="p">.</span><span class="n">instream</span><span class="w"></span>\r |
| 61 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">textOut</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">TextIO</span><span class="p">.</span><span class="n">outstream</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">TextIO</span><span class="p">.</span><span class="n">outstream</span><span class="w"></span>\r |
| 62 | <span class="w"> </span><span class="k">end</span><span class="w"></span>\r |
| 63 | \r |
| 64 | <span class="w"> </span><span class="k">structure</span><span class="w"> </span><span class="n">Param</span><span class="p">:</span><span class="w"></span>\r |
| 65 | <span class="w"> </span><span class="k">sig</span><span class="w"></span>\r |
| 66 | <span class="w"> </span><span class="k">type</span><span class="w"> </span><span class="p">(</span><span class="n">'use</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 67 | \r |
| 68 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">child</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">chain</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">Child</span><span class="p">.</span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">none</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 69 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">fd</span><span class="p">:</span><span class="w"> </span><span class="n">Posix</span><span class="p">.</span><span class="n">FileSys</span><span class="p">.</span><span class="n">file_desc</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">none</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 70 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">file</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">none</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 71 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">forget</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'use</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">any</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 72 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">null</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">none</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 73 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">pipe</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'use</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 74 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">self</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">none</span><span class="p">,</span><span class="w"> </span><span class="n">'dir</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 75 | <span class="w"> </span><span class="k">end</span><span class="w"></span>\r |
| 76 | \r |
| 77 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">create</span><span class="p">:</span><span class="w"></span>\r |
| 78 | <span class="w"> </span><span class="p">{</span><span class="n">args</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">list</span><span class="p">,</span><span class="w"></span>\r |
| 79 | <span class="w"> </span><span class="n">env</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="w"> </span><span class="n">list</span><span class="w"> </span><span class="n">option</span><span class="p">,</span><span class="w"></span>\r |
| 80 | <span class="w"> </span><span class="n">path</span><span class="p">:</span><span class="w"> </span><span class="n">string</span><span class="p">,</span><span class="w"></span>\r |
| 81 | <span class="w"> </span><span class="n">stderr</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stderr</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">)</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">t</span><span class="p">,</span><span class="w"></span>\r |
| 82 | <span class="w"> </span><span class="n">stdin</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">input</span><span class="p">)</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">t</span><span class="p">,</span><span class="w"></span>\r |
| 83 | <span class="w"> </span><span class="n">stdout</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">)</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">t</span><span class="p">}</span><span class="w"></span>\r |
| 84 | <span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"></span>\r |
| 85 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">getStderr</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">'stderr</span><span class="p">,</span><span class="w"> </span><span class="n">input</span><span class="p">)</span><span class="w"> </span><span class="n">Child</span><span class="p">.</span><span class="n">t</span><span class="w"></span>\r |
| 86 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">getStdin</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">output</span><span class="p">)</span><span class="w"> </span><span class="n">Child</span><span class="p">.</span><span class="n">t</span><span class="w"></span>\r |
| 87 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">getStdout</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="p">(</span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">input</span><span class="p">)</span><span class="w"> </span><span class="n">Child</span><span class="p">.</span><span class="n">t</span><span class="w"></span>\r |
| 88 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">kill</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="n">*</span><span class="w"> </span><span class="n">Posix</span><span class="p">.</span><span class="n">Signal</span><span class="p">.</span><span class="n">signal</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">unit</span><span class="w"></span>\r |
| 89 | <span class="w"> </span><span class="k">val</span><span class="w"> </span><span class="n">reap</span><span class="p">:</span><span class="w"> </span><span class="p">(</span><span class="n">'stdin</span><span class="p">,</span><span class="w"> </span><span class="n">'stdout</span><span class="p">,</span><span class="w"> </span><span class="n">'stderr</span><span class="p">)</span><span class="w"> </span><span class="n">t</span><span class="w"> </span><span class="p">-></span><span class="w"> </span><span class="n">Posix</span><span class="p">.</span><span class="n">Process</span><span class="p">.</span><span class="n">exit_status</span><span class="w"></span>\r |
| 90 | <span class="w"> </span><span class="k">end</span><span class="w"></span>\r |
| 91 | </pre></div></div></div>\r |
| 92 | </div>\r |
| 93 | </div>\r |
| 94 | <div class="sect1">\r |
| 95 | <h2 id="_spawn">Spawn</h2>\r |
| 96 | <div class="sectionbody">\r |
| 97 | <div class="paragraph"><p>The <span class="monospaced">spawn</span> functions provide an alternative to the\r |
| 98 | <span class="monospaced">fork</span>/<span class="monospaced">exec</span> idiom that is typically used to create a new\r |
| 99 | process. On most platforms, the <span class="monospaced">spawn</span> functions are simple\r |
| 100 | wrappers around <span class="monospaced">fork</span>/<span class="monospaced">exec</span>. However, under Windows, the\r |
| 101 | <span class="monospaced">spawn</span> functions are primitive. All <span class="monospaced">spawn</span> functions return\r |
| 102 | the process id of the spawned process. They differ in how the\r |
| 103 | executable is found and the environment that it uses.</p></div>\r |
| 104 | <div class="ulist"><ul>\r |
| 105 | <li>\r |
| 106 | <p>\r |
| 107 | <span class="monospaced">spawn {args, path}</span>\r |
| 108 | </p>\r |
| 109 | <div class="paragraph"><p>starts a new process running the executable specified by <span class="monospaced">path</span>\r |
| 110 | with the arguments <span class="monospaced">args</span>. Like <span class="monospaced">Posix.Process.exec</span>.</p></div>\r |
| 111 | </li>\r |
| 112 | <li>\r |
| 113 | <p>\r |
| 114 | <span class="monospaced">spawne {args, env, path}</span>\r |
| 115 | </p>\r |
| 116 | <div class="paragraph"><p>starts a new process running the executable specified by <span class="monospaced">path</span> with\r |
| 117 | the arguments <span class="monospaced">args</span> and environment <span class="monospaced">env</span>. Like\r |
| 118 | <span class="monospaced">Posix.Process.exece</span>.</p></div>\r |
| 119 | </li>\r |
| 120 | <li>\r |
| 121 | <p>\r |
| 122 | <span class="monospaced">spawnp {args, file}</span>\r |
| 123 | </p>\r |
| 124 | <div class="paragraph"><p>search the <span class="monospaced">PATH</span> environment variable for an executable named <span class="monospaced">file</span>,\r |
| 125 | and start a new process running that executable with the arguments\r |
| 126 | <span class="monospaced">args</span>. Like <span class="monospaced">Posix.Process.execp</span>.</p></div>\r |
| 127 | </li>\r |
| 128 | </ul></div>\r |
| 129 | </div>\r |
| 130 | </div>\r |
| 131 | <div class="sect1">\r |
| 132 | <h2 id="_create">Create</h2>\r |
| 133 | <div class="sectionbody">\r |
| 134 | <div class="paragraph"><p><span class="monospaced">MLton.Process.create</span> provides functionality similar to\r |
| 135 | <span class="monospaced">Unix.executeInEnv</span>, but provides more control control over the input,\r |
| 136 | output, and error streams. In addition, <span class="monospaced">create</span> works on all\r |
| 137 | platforms, including Cygwin and MinGW (Windows) where <span class="monospaced">Posix.fork</span> is\r |
| 138 | unavailable. For greatest portability programs should still use the\r |
| 139 | standard <span class="monospaced">Unix.execute</span>, <span class="monospaced">Unix.executeInEnv</span>, and <span class="monospaced">OS.Process.system</span>.</p></div>\r |
| 140 | <div class="paragraph"><p>The following types and sub-structures are used by the <span class="monospaced">create</span>\r |
| 141 | function. They provide static type checking of correct stream usage.</p></div>\r |
| 142 | <div class="sect2">\r |
| 143 | <h3 id="_child">Child</h3>\r |
| 144 | <div class="ulist"><ul>\r |
| 145 | <li>\r |
| 146 | <p>\r |
| 147 | <span class="monospaced">('use, 'dir) Child.t</span>\r |
| 148 | </p>\r |
| 149 | <div class="paragraph"><p>This represents a handle to one of a child’s standard streams. The\r |
| 150 | <span class="monospaced">'dir</span> is viewed with respect to the parent. Thus a <span class="monospaced">('a, input)\r |
| 151 | Child.t</span> handle means that the parent may input the output from the\r |
| 152 | child.</p></div>\r |
| 153 | </li>\r |
| 154 | <li>\r |
| 155 | <p>\r |
| 156 | <span class="monospaced">Child.{bin,text}{In,Out} h</span>\r |
| 157 | </p>\r |
| 158 | <div class="paragraph"><p>These functions take a handle and bind it to a stream of the named\r |
| 159 | type. The type system will detect attempts to reverse the direction\r |
| 160 | of a stream or to use the same stream in multiple, incompatible ways.</p></div>\r |
| 161 | </li>\r |
| 162 | <li>\r |
| 163 | <p>\r |
| 164 | <span class="monospaced">Child.fd h</span>\r |
| 165 | </p>\r |
| 166 | <div class="paragraph"><p>This function behaves like the other <span class="monospaced">Child.*</span> functions; it opens a\r |
| 167 | stream. However, it does not enforce that you read or write from the\r |
| 168 | handle. If you use the descriptor in an inappropriate direction, the\r |
| 169 | behavior is undefined. Furthermore, this function may potentially be\r |
| 170 | unavailable on future MLton host platforms.</p></div>\r |
| 171 | </li>\r |
| 172 | <li>\r |
| 173 | <p>\r |
| 174 | <span class="monospaced">Child.remember h</span>\r |
| 175 | </p>\r |
| 176 | <div class="paragraph"><p>This function takes a stream of use <span class="monospaced">any</span> and resets the use of the\r |
| 177 | stream so that the stream may be used by <span class="monospaced">Child.*</span>. An <span class="monospaced">any</span> stream\r |
| 178 | may have had use <span class="monospaced">none</span> or <span class="monospaced">'use</span> prior to calling <span class="monospaced">Param.forget</span>. If\r |
| 179 | the stream was <span class="monospaced">none</span> and is used, <span class="monospaced">MisuseOfForget</span> is raised.</p></div>\r |
| 180 | </li>\r |
| 181 | </ul></div>\r |
| 182 | </div>\r |
| 183 | <div class="sect2">\r |
| 184 | <h3 id="_param">Param</h3>\r |
| 185 | <div class="ulist"><ul>\r |
| 186 | <li>\r |
| 187 | <p>\r |
| 188 | <span class="monospaced">('use, 'dir) Param.t</span>\r |
| 189 | </p>\r |
| 190 | <div class="paragraph"><p>This is a handle to an input/output source and will be passed to the\r |
| 191 | created child process. The <span class="monospaced">'dir</span> is relative to the child process.\r |
| 192 | Input means that the child process will read from this stream.</p></div>\r |
| 193 | </li>\r |
| 194 | <li>\r |
| 195 | <p>\r |
| 196 | <span class="monospaced">Param.child h</span>\r |
| 197 | </p>\r |
| 198 | <div class="paragraph"><p>Connect the stream of the new child process to the stream of a\r |
| 199 | previously created child process. A single child stream should be\r |
| 200 | connected to only one child process or else <span class="monospaced">DoublyRedirected</span> will be\r |
| 201 | raised.</p></div>\r |
| 202 | </li>\r |
| 203 | <li>\r |
| 204 | <p>\r |
| 205 | <span class="monospaced">Param.fd fd</span>\r |
| 206 | </p>\r |
| 207 | <div class="paragraph"><p>This creates a stream from the provided file descriptor which will be\r |
| 208 | closed when <span class="monospaced">create</span> is called. This function may not be available on\r |
| 209 | future MLton host platforms.</p></div>\r |
| 210 | </li>\r |
| 211 | <li>\r |
| 212 | <p>\r |
| 213 | <span class="monospaced">Param.forget h</span>\r |
| 214 | </p>\r |
| 215 | <div class="paragraph"><p>This hides the type of the actual parameter as <span class="monospaced">any</span>. This is useful\r |
| 216 | if you are implementing an application which conditionally attaches\r |
| 217 | the child process to files or pipes. However, you must ensure that\r |
| 218 | your use after <span class="monospaced">Child.remember</span> matches the original type.</p></div>\r |
| 219 | </li>\r |
| 220 | <li>\r |
| 221 | <p>\r |
| 222 | <span class="monospaced">Param.file s</span>\r |
| 223 | </p>\r |
| 224 | <div class="paragraph"><p>Open the given file and connect it to the child process. Note that the\r |
| 225 | file will be opened only when <span class="monospaced">create</span> is called. So any exceptions\r |
| 226 | will be raised there and not by this function. If used for <span class="monospaced">input</span>,\r |
| 227 | the file is opened read-only. If used for <span class="monospaced">output</span>, the file is opened\r |
| 228 | read-write.</p></div>\r |
| 229 | </li>\r |
| 230 | <li>\r |
| 231 | <p>\r |
| 232 | <span class="monospaced">Param.null</span>\r |
| 233 | </p>\r |
| 234 | <div class="paragraph"><p>In some situations, the child process should have its output\r |
| 235 | discarded. The <span class="monospaced">null</span> param when passed as <span class="monospaced">stdout</span> or <span class="monospaced">stderr</span> does\r |
| 236 | this. When used for <span class="monospaced">stdin</span>, the child process will either receive\r |
| 237 | <span class="monospaced">EOF</span> or a failure condition if it attempts to read from <span class="monospaced">stdin</span>.</p></div>\r |
| 238 | </li>\r |
| 239 | <li>\r |
| 240 | <p>\r |
| 241 | <span class="monospaced">Param.pipe</span>\r |
| 242 | </p>\r |
| 243 | <div class="paragraph"><p>This will connect the input/output of the child process to a pipe\r |
| 244 | which the parent process holds. This may later form the input to one\r |
| 245 | of the <span class="monospaced">Child.*</span> functions and/or the <span class="monospaced">Param.child</span> function.</p></div>\r |
| 246 | </li>\r |
| 247 | <li>\r |
| 248 | <p>\r |
| 249 | <span class="monospaced">Param.self</span>\r |
| 250 | </p>\r |
| 251 | <div class="paragraph"><p>This will connect the input/output of the child process to the\r |
| 252 | corresponding stream of the parent process.</p></div>\r |
| 253 | </li>\r |
| 254 | </ul></div>\r |
| 255 | </div>\r |
| 256 | <div class="sect2">\r |
| 257 | <h3 id="_process">Process</h3>\r |
| 258 | <div class="ulist"><ul>\r |
| 259 | <li>\r |
| 260 | <p>\r |
| 261 | <span class="monospaced">type ('stdin, 'stdout, 'stderr) t</span>\r |
| 262 | </p>\r |
| 263 | <div class="paragraph"><p>represents a handle to a child process. The type arguments capture\r |
| 264 | how the named stream of the child process may be used.</p></div>\r |
| 265 | </li>\r |
| 266 | <li>\r |
| 267 | <p>\r |
| 268 | <span class="monospaced">type any</span>\r |
| 269 | </p>\r |
| 270 | <div class="paragraph"><p>bypasses the type system in situations where an application does not\r |
| 271 | want the it to enforce correct usage. See <span class="monospaced">Child.remember</span> and\r |
| 272 | <span class="monospaced">Param.forget</span>.</p></div>\r |
| 273 | </li>\r |
| 274 | <li>\r |
| 275 | <p>\r |
| 276 | <span class="monospaced">type chain</span>\r |
| 277 | </p>\r |
| 278 | <div class="paragraph"><p>means that the child process’s stream was connected via a pipe to the\r |
| 279 | parent process. The parent process may pass this pipe in turn to\r |
| 280 | another child, thus chaining them together.</p></div>\r |
| 281 | </li>\r |
| 282 | <li>\r |
| 283 | <p>\r |
| 284 | <span class="monospaced">type input, output</span>\r |
| 285 | </p>\r |
| 286 | <div class="paragraph"><p>record the direction that a stream flows. They are used as a part of\r |
| 287 | <span class="monospaced">Param.t</span> and <span class="monospaced">Child.t</span> and is detailed there.</p></div>\r |
| 288 | </li>\r |
| 289 | <li>\r |
| 290 | <p>\r |
| 291 | <span class="monospaced">type none</span>\r |
| 292 | </p>\r |
| 293 | <div class="paragraph"><p>means that the child process’s stream my not be used by the parent\r |
| 294 | process. This happens when the child process is connected directly to\r |
| 295 | some source.</p></div>\r |
| 296 | <div class="paragraph"><p>The types <span class="monospaced">BinIO.instream</span>, <span class="monospaced">BinIO.outstream</span>, <span class="monospaced">TextIO.instream</span>,\r |
| 297 | <span class="monospaced">TextIO.outstream</span>, and <span class="monospaced">Posix.FileSys.file_desc</span> are also valid types\r |
| 298 | with which to instantiate child streams.</p></div>\r |
| 299 | </li>\r |
| 300 | <li>\r |
| 301 | <p>\r |
| 302 | <span class="monospaced">exception MisuseOfForget</span>\r |
| 303 | </p>\r |
| 304 | <div class="paragraph"><p>may be raised if <span class="monospaced">Child.remember</span> and <span class="monospaced">Param.forget</span> are used to\r |
| 305 | bypass the normal type checking. This exception will only be raised\r |
| 306 | in cases where the <span class="monospaced">forget</span> mechanism allows a misuse that would be\r |
| 307 | impossible with the type-safe versions.</p></div>\r |
| 308 | </li>\r |
| 309 | <li>\r |
| 310 | <p>\r |
| 311 | <span class="monospaced">exception DoublyRedirected</span>\r |
| 312 | </p>\r |
| 313 | <div class="paragraph"><p>raised if a stream connected to a child process is redirected to two\r |
| 314 | separate child processes. It is safe, though bad style, to use the a\r |
| 315 | <span class="monospaced">Child.t</span> with the same <span class="monospaced">Child.*</span> function repeatedly.</p></div>\r |
| 316 | </li>\r |
| 317 | <li>\r |
| 318 | <p>\r |
| 319 | <span class="monospaced">create {args, path, env, stderr, stdin, stdout}</span>\r |
| 320 | </p>\r |
| 321 | <div class="paragraph"><p>starts a child process with the given command-line <span class="monospaced">args</span> (excluding\r |
| 322 | the program name). <span class="monospaced">path</span> should be an absolute path to the executable\r |
| 323 | run in the new child process; relative paths work, but are less\r |
| 324 | robust. Optionally, the environment may be overridden with <span class="monospaced">env</span>\r |
| 325 | where each string element has the form <span class="monospaced">"key=value"</span>. The <span class="monospaced">std*</span>\r |
| 326 | options must be provided by the <span class="monospaced">Param.*</span> functions documented above.</p></div>\r |
| 327 | <div class="paragraph"><p>Processes which are <span class="monospaced">create</span>-d must be either <span class="monospaced">reap</span>-ed or <span class="monospaced">kill</span>-ed.</p></div>\r |
| 328 | </li>\r |
| 329 | <li>\r |
| 330 | <p>\r |
| 331 | <span class="monospaced">getStd{in,out,err} proc</span>\r |
| 332 | </p>\r |
| 333 | <div class="paragraph"><p>gets a handle to the specified stream. These should be used by the\r |
| 334 | <span class="monospaced">Child.*</span> functions. Failure to use a stream connected via pipe to a\r |
| 335 | child process may result in runtime dead-lock and elicits a compiler\r |
| 336 | warning.</p></div>\r |
| 337 | </li>\r |
| 338 | <li>\r |
| 339 | <p>\r |
| 340 | <span class="monospaced">kill (proc, sig)</span>\r |
| 341 | </p>\r |
| 342 | <div class="paragraph"><p>terminates the child process immediately. The signal may or may not\r |
| 343 | mean anything depending on the host platform. A good value is\r |
| 344 | <span class="monospaced">Posix.Signal.term</span>.</p></div>\r |
| 345 | </li>\r |
| 346 | <li>\r |
| 347 | <p>\r |
| 348 | <span class="monospaced">reap proc</span>\r |
| 349 | </p>\r |
| 350 | <div class="paragraph"><p>waits for the child process to terminate and return its exit status.</p></div>\r |
| 351 | </li>\r |
| 352 | </ul></div>\r |
| 353 | </div>\r |
| 354 | </div>\r |
| 355 | </div>\r |
| 356 | <div class="sect1">\r |
| 357 | <h2 id="_important_usage_notes">Important usage notes</h2>\r |
| 358 | <div class="sectionbody">\r |
| 359 | <div class="paragraph"><p>When building an application with many pipes between child processes,\r |
| 360 | it is important to ensure that there are no cycles in the undirected\r |
| 361 | pipe graph. If this property is not maintained, deadlocks are a very\r |
| 362 | serious potential bug which may only appear under difficult to\r |
| 363 | reproduce conditions.</p></div>\r |
| 364 | <div class="paragraph"><p>The danger lies in that most operating systems implement pipes with a\r |
| 365 | fixed buffer size. If process A has two output pipes which process B\r |
| 366 | reads, it can happen that process A blocks writing to pipe 2 because\r |
| 367 | it is full while process B blocks reading from pipe 1 because it is\r |
| 368 | empty. This same situation can happen with any undirected cycle formed\r |
| 369 | between processes (vertexes) and pipes (undirected edges) in the\r |
| 370 | graph.</p></div>\r |
| 371 | <div class="paragraph"><p>It is possible to make this safe using low-level I/O primitives for\r |
| 372 | polling. However, these primitives are not very portable and\r |
| 373 | difficult to use properly. A far better approach is to make sure you\r |
| 374 | never create a cycle in the first place.</p></div>\r |
| 375 | <div class="paragraph"><p>For these reasons, the <span class="monospaced">Unix.executeInEnv</span> is a very dangerous\r |
| 376 | function. Be careful when using it to ensure that the child process\r |
| 377 | only operates on either <span class="monospaced">stdin</span> or <span class="monospaced">stdout</span>, but not both.</p></div>\r |
| 378 | </div>\r |
| 379 | </div>\r |
| 380 | <div class="sect1">\r |
| 381 | <h2 id="_example_use_of_mlton_process_create">Example use of MLton.Process.create</h2>\r |
| 382 | <div class="sectionbody">\r |
| 383 | <div class="paragraph"><p>The following example program launches the <span class="monospaced">ipconfig</span> utility, pipes\r |
| 384 | its output through <span class="monospaced">grep</span>, and then reads the result back into the\r |
| 385 | program.</p></div>\r |
| 386 | <div class="listingblock">\r |
| 387 | <div class="content"><div class="highlight"><pre><span class="k">open</span><span class="w"> </span><span class="n">MLton</span><span class="p">.</span><span class="n">Process</span><span class="w"></span>\r |
| 388 | <span class="k">val</span><span class="w"> </span><span class="n">p</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r |
| 389 | <span class="w"> </span><span class="n">create</span><span class="w"> </span><span class="p">{</span><span class="n">args</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s">"/all"</span><span class="w"> </span><span class="p">],</span><span class="w"></span>\r |
| 390 | <span class="w"> </span><span class="n">env</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">NONE</span><span class="p">,</span><span class="w"></span>\r |
| 391 | <span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">"C:</span><span class="se">\\</span><span class="s">WINDOWS</span><span class="se">\\</span><span class="s">system32</span><span class="se">\\</span><span class="s">ipconfig.exe"</span><span class="p">,</span><span class="w"></span>\r |
| 392 | <span class="w"> </span><span class="n">stderr</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">self</span><span class="p">,</span><span class="w"></span>\r |
| 393 | <span class="w"> </span><span class="n">stdin</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">null</span><span class="p">,</span><span class="w"></span>\r |
| 394 | <span class="w"> </span><span class="n">stdout</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">pipe</span><span class="p">}</span><span class="w"></span>\r |
| 395 | <span class="k">val</span><span class="w"> </span><span class="n">q</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r |
| 396 | <span class="w"> </span><span class="n">create</span><span class="w"> </span><span class="p">{</span><span class="n">args</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="p">[</span><span class="w"> </span><span class="s">"IP-Ad"</span><span class="w"> </span><span class="p">],</span><span class="w"></span>\r |
| 397 | <span class="w"> </span><span class="n">env</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">NONE</span><span class="p">,</span><span class="w"></span>\r |
| 398 | <span class="w"> </span><span class="n">path</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="s">"C:</span><span class="se">\\</span><span class="s">msys</span><span class="se">\\</span><span class="s">bin</span><span class="se">\\</span><span class="s">grep.exe"</span><span class="p">,</span><span class="w"></span>\r |
| 399 | <span class="w"> </span><span class="n">stderr</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">self</span><span class="p">,</span><span class="w"></span>\r |
| 400 | <span class="w"> </span><span class="n">stdin</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">child</span><span class="w"> </span><span class="p">(</span><span class="n">getStdout</span><span class="w"> </span><span class="n">p</span><span class="p">),</span><span class="w"></span>\r |
| 401 | <span class="w"> </span><span class="n">stdout</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">Param</span><span class="p">.</span><span class="n">pipe</span><span class="p">}</span><span class="w"></span>\r |
| 402 | <span class="k">fun</span><span class="w"> </span><span class="n">suck</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="p">=</span><span class="w"></span>\r |
| 403 | <span class="w"> </span><span class="k">case</span><span class="w"> </span><span class="n">TextIO</span><span class="p">.</span><span class="n">inputLine</span><span class="w"> </span><span class="n">h</span><span class="w"> </span><span class="k">of</span><span class="w"></span>\r |
| 404 | <span class="w"> </span><span class="n">NONE</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="p">()</span><span class="w"></span>\r |
| 405 | <span class="w"> </span><span class="p">|</span><span class="w"> </span><span class="n">SOME</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="p">=></span><span class="w"> </span><span class="p">(</span><span class="n">print</span><span class="w"> </span><span class="p">(</span><span class="s">"'"</span><span class="w"> </span><span class="n">^</span><span class="w"> </span><span class="n">s</span><span class="w"> </span><span class="n">^</span><span class="w"> </span><span class="s">"'</span><span class="se">\n</span><span class="s">"</span><span class="p">);</span><span class="w"> </span><span class="n">suck</span><span class="w"> </span><span class="n">h</span><span class="p">)</span><span class="w"></span>\r |
| 406 | \r |
| 407 | <span class="k">val</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="p">=</span><span class="w"> </span><span class="n">suck</span><span class="w"> </span><span class="p">(</span><span class="n">Child</span><span class="p">.</span><span class="n">textIn</span><span class="w"> </span><span class="p">(</span><span class="n">getStdout</span><span class="w"> </span><span class="n">q</span><span class="p">))</span><span class="w"></span>\r |
| 408 | </pre></div></div></div>\r |
| 409 | </div>\r |
| 410 | </div>\r |
| 411 | </div>\r |
| 412 | <div id="footnotes"><hr></div>\r |
| 413 | <div id="footer">\r |
| 414 | <div id="footer-text">\r |
| 415 | </div>\r |
| 416 | <div id="footer-badges">\r |
| 417 | </div>\r |
| 418 | </div>\r |
| 419 | </body>\r |
| 420 | </html>\r |