{"id":82,"date":"2010-05-13T01:02:27","date_gmt":"2010-05-13T05:02:27","guid":{"rendered":"http:\/\/adamrosenfield.com\/blog\/?p=82"},"modified":"2011-02-23T02:27:12","modified_gmt":"2011-02-23T06:27:12","slug":"so-whats-in-an-exit-status-anyways","status":"publish","type":"post","link":"http:\/\/adamrosenfield.com\/blog\/2010\/05\/13\/so-whats-in-an-exit-status-anyways\/","title":{"rendered":"So what&#8217;s in an exit status anyways?"},"content":{"rendered":"<p><a href=\"http:\/\/adamrosenfield.com\/blog\/2010\/04\/23\/dumping-core\/\">Last time<\/a>, we saw how we can capture a process&#8217; core dump.  The astute reader will have noticed that we seem to be pulling bits out of thin air:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">int status;\r\nif(wait(&amp;status) &lt; 0)\r\n  perror(&quot;wait&quot;);\r\nif(WIFSIGNALED(status) &amp;&amp; WCOREDUMP(status))\r\n...<\/pre>\n<p>We&#8217;ve got a 32-bit exit status, and yet we seem to getting two more useful bits of information out of it from the <code>WIFSIGNALED()<\/code> and <code>WCOREDUMP()<\/code> macros.  How is that possible?<\/p>\n<p>Well, what you thought was a 32-bit exit status really isn&#8217;t 32 bits.  In fact, it&#8217;s quite a bit less than.  The C standard only guarantees one useful bit.  Quoth section 7.20.4.3, paragraph 5, of the <a href=\"http:\/\/c-faq.com\/ansi\/avail.html\">C99 standard<\/a>, which describes the <a href=\"http:\/\/linux.die.net\/man\/3\/exit\"><code>exit(3)<\/code><\/a> function:<\/p>\n<blockquote><p>Finally, control is returned to the host environment. If the value of <code>status<\/code> is zero or <code>EXIT_SUCCESS<\/code>, an implementation-defined form of the status <em>successful termination<\/em> is returned. If the value of <code>status<\/code> is <code>EXIT_FAILURE<\/code>, an implementation-defined form of the status <em>unsuccessful termination<\/em> is returned. Otherwise the status returned is implementation-defined.<\/p><\/blockquote>\n<p>Recall that <em>implementation-defined<\/em> means the C standard doesn&#8217;t define what happens, but the <em>implementation<\/em> (in this case, the GNU C library, or the Microsoft C library, etc.) <b>must document<\/b> the decision it made.  Contrast this with <em>undefined behavior<\/em>, in which anything could happen (including erasing your hard drive), and nowhere does what happens have to be documented.<\/p>\n<p>So if you want to write portable code, you only get one bit of information in your exit status: successful or unsuccessful termination, which is often good enough for most applications.  If you go this route, it&#8217;s a good idea to use the <code>EXIT_SUCCESS<\/code> and <code>EXIT_FAILURE<\/code> macros, but it&#8217;s by no means necessary.  You can use still use 0 and something non-0 (1 is a popular\u2014and good\u2014choice), and it will still work pretty much anywhere if you&#8217;re not unlucky.  But the only truly 100% portable unsuccessful status is <code>EXIT_FAILURE<\/code>.<\/p>\n<p>Screw that.  You want more than one bit of information in your exit status.  There&#8217;s a whole 32 bits (or occasionally 16 or 64 on some non-standard systems) in an <code>int<\/code>, so why can&#8217;t we use them?  On Linux, the <a href=\"http:\/\/linux.die.net\/man\/3\/exit\"><code>exit(3)<\/code> man page<\/a> clearly states we get 8 bits:<\/p>\n<blockquote><p>The <b>exit()<\/b> function causes normal process termination and the value of <em>status &amp; 0377<\/em> is returned to the parent (see <em><b><a href=\"http:\/\/linux.die.net\/man\/2\/wait\">wait<\/a><\/b>(2)<\/em>).<\/p><\/blockquote>\n<p><a href=\"http:\/\/developer.apple.com\/mac\/library\/documentation\/Darwin\/Reference\/ManPages\/man3\/exit.3.html\">Mac OS X<\/a> likewise also provides 8 bits (though that fact is a little more subtle in the documentation there).  Windows fares better here\u2014it provides the full 32 bits via the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms683189%28v=VS.85%29.aspx\"><code>GetExitCodeProcess()<\/code><\/a> function here\u2014but the discussion here is going to focus on Linux\/Mac OS X for now.<\/p>\n<p>8 bits.  Much more useful than 1, though not quite the 32 you might have been hoping for.  It&#8217;s enough to express a varied gamut of exit statuses (<em>incorrect usage<\/em>, <em>file not found<\/em>, <em>other unexpected error<\/em>, etc.).<\/p>\n<p>A consequence of this behavior is if you exit with a status that is a multiple of 256, that&#8217;s indistinguishable from 0, which means you&#8217;re likely exiting with a successful status when you meant it to be unsuccessful.  Oops.<\/p>\n<p>As a quick example, try out these shell commands (<code>$?<\/code> is a <a href=\"http:\/\/www.gnu.org\/software\/bash\/manual\/bashref.html#Special-Parameters\">special parameter<\/a> that evaluates to the exit status of the last child process or pipeline ran by the shell):<\/p>\n<pre>$ bash -c 'exit 5'; echo $?     # Prints 5\r\n$ bash -c 'exit 256'; echo $?   # Prints 0 (!)<\/pre>\n<p>Now that we&#8217;ve figured out we only have 8 bits that come with an exit status, it&#8217;s clear how the <code>WIFSIGNALED()<\/code> and <code>WCOREDUMP()<\/code> macros work: <a href=\"http:\/\/linux.die.net\/man\/2\/wait\"><code>wait(2)<\/code><\/a> stuffs extra information into the status in addition to the child process&#8217; exit status (you could have figured that out by reading the man page, but you obviously didn&#8217;t since you&#8217;re here reading this).<\/p>\n<p>One final word of caution: be careful about exit statuses above 128.  When a process is terminated due to a signal (say, because it segfaulted, resulting in a <code>SIGSEGV<\/code>), the exit status is 128 plus the signal number.  Yes, a parent process can tell if the child process was terminated by a signal or by calling <code>exit()<\/code> by checking with <code>WIFSIGNALED()<\/code>, but it&#8217;s not always possible to get at that information when you want it.  If you&#8217;re executing commands in the bash shell, you can get at the exit status quite easily with <code>$?<\/code>, but you can&#8217;t get at the other bits returned by <code>wait()<\/code>, at least not in any way I know.  To keep things simple, if you never use exit statuses above 128, then anyone can unambiguously determine that an exit status of 0\u2013127 means a normal exit, and an exit status of 128\u2013255 means an abnormal exit.<\/p>\n<p>In summary, use only <code>EXIT_SUCCESS<\/code> and <code>EXIT_FAILURE<\/code> for maximally portable code, and otherwise use only 0\u2013127 for code that will be portable to Linux, Mac OS X, and Windows (and probably other not-uncommon systems that are still in current us but with which I&#8217;m not familiar enough to comment on).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Last time, we saw how we can capture a process&#8217; core dump. The astute reader will have noticed that we seem to be pulling bits out of thin air: int status; if(wait(&amp;status) &lt; 0) perror(&quot;wait&quot;); if(WIFSIGNALED(status) &amp;&amp; WCOREDUMP(status)) &#8230; We&#8217;ve got a 32-bit exit status, and yet we seem to getting two more useful bits [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[],"class_list":["post-82","post","type-post","status-publish","format-standard","hentry","category-programming"],"_links":{"self":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts\/82","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/comments?post=82"}],"version-history":[{"count":8,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts\/82\/revisions"}],"predecessor-version":[{"id":195,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/posts\/82\/revisions\/195"}],"wp:attachment":[{"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/media?parent=82"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/categories?post=82"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/adamrosenfield.com\/blog\/wp-json\/wp\/v2\/tags?post=82"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}