Sophie

Sophie

distrib > Mandriva > 2007.0 > x86_64 > media > main-release > by-pkgid > 926d2d1e3111287cee1b0a4fad4fb4f6 > files > 124

lib64dbus-1_3-devel-0.92-6mdv2007.0.x86_64.rpm

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
<title>dbus-spawn.c Source File</title>
<link href="doxygen.css" rel="stylesheet" type="text/css">
</head><body>
<!-- Generated by Doxygen 1.2.15 -->
<center>
<a class="qindex" href="index.html">Main Page</a> &nbsp; <a class="qindex" href="modules.html">Modules</a> &nbsp; <a class="qindex" href="annotated.html">Data Structures</a> &nbsp; <a class="qindex" href="files.html">File List</a> &nbsp; <a class="qindex" href="functions.html">Data Fields</a> &nbsp; <a class="qindex" href="pages.html">Related Pages</a> &nbsp; </center>
<hr><h1>dbus-spawn.c</h1><div class="fragment"><pre>00001 <font class="comment">/* -*- mode: C; c-file-style: "gnu" -*- */</font>
00002 <font class="comment">/* dbus-spawn.c Wrapper around fork/exec</font>
00003 <font class="comment"> * </font>
00004 <font class="comment"> * Copyright (C) 2002, 2003  Red Hat, Inc.</font>
00005 <font class="comment"> * Copyright (C) 2003 CodeFactory AB</font>
00006 <font class="comment"> *</font>
00007 <font class="comment"> * Licensed under the Academic Free License version 2.0</font>
00008 <font class="comment"> * </font>
00009 <font class="comment"> * This program is free software; you can redistribute it and/or modify</font>
00010 <font class="comment"> * it under the terms of the GNU General Public License as published by</font>
00011 <font class="comment"> * the Free Software Foundation; either version 2 of the License, or</font>
00012 <font class="comment"> * (at your option) any later version.</font>
00013 <font class="comment"> *</font>
00014 <font class="comment"> * This program is distributed in the hope that it will be useful,</font>
00015 <font class="comment"> * but WITHOUT ANY WARRANTY; without even the implied warranty of</font>
00016 <font class="comment"> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</font>
00017 <font class="comment"> * GNU General Public License for more details.</font>
00018 <font class="comment"> * </font>
00019 <font class="comment"> * You should have received a copy of the GNU General Public License</font>
00020 <font class="comment"> * along with this program; if not, write to the Free Software</font>
00021 <font class="comment"> * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA</font>
00022 <font class="comment"> *</font>
00023 <font class="comment"> */</font>
00024 <font class="preprocessor">#include "dbus-spawn.h"</font>
00025 <font class="preprocessor">#include "dbus-sysdeps.h"</font>
00026 <font class="preprocessor">#include "dbus-internals.h"</font>
00027 <font class="preprocessor">#include "dbus-test.h"</font>
00028 
00029 <font class="preprocessor">#include &lt;unistd.h&gt;</font>
00030 <font class="preprocessor">#include &lt;fcntl.h&gt;</font>
00031 <font class="preprocessor">#include &lt;signal.h&gt;</font>
00032 <font class="preprocessor">#include &lt;sys/wait.h&gt;</font>
00033 <font class="preprocessor">#include &lt;errno.h&gt;</font>
00034 <font class="preprocessor">#include &lt;stdlib.h&gt;</font>
00035 
00041 <font class="comment">/*</font>
00042 <font class="comment"> * I'm pretty sure this whole spawn file could be made simpler,</font>
00043 <font class="comment"> * if you thought about it a bit.</font>
00044 <font class="comment"> */</font>
00045 
<a name="l00049"></a><a class="code" href="group__DBusInternalsUtils.html#a153">00049</a> <font class="keyword">typedef</font> <font class="keyword">enum</font>
00050 {
00051   READ_STATUS_OK,    
00052   READ_STATUS_ERROR, 
00053   READ_STATUS_EOF    
00054 } ReadStatus;
00055 
00056 <font class="keyword">static</font> ReadStatus
00057 read_ints (<font class="keywordtype">int</font>        fd,
00058            <font class="keywordtype">int</font>       *buf,
00059            <font class="keywordtype">int</font>        n_ints_in_buf,
00060            <font class="keywordtype">int</font>       *n_ints_read,
00061            <a class="code" href="structDBusError.html">DBusError</a> *error)
00062 {
00063   size_t bytes = 0;    
00064   ReadStatus retval;
00065   
00066   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00067 
00068   retval = READ_STATUS_OK;
00069   
00070   <font class="keywordflow">while</font> (TRUE)
00071     {
00072       size_t chunk;
00073       size_t to_read;
00074       
00075     again:
00076 
00077       to_read = <font class="keyword">sizeof</font> (int) * n_ints_in_buf - bytes;
00078 
00079       <font class="keywordflow">if</font> (to_read == 0)
00080         <font class="keywordflow">break</font>;
00081       
00082       chunk = read (fd,
00083                     ((<font class="keywordtype">char</font>*)buf) + bytes,
00084                     to_read);
00085       
00086       <font class="keywordflow">if</font> (chunk &lt; 0 &amp;&amp; errno == EINTR)
00087         <font class="keywordflow">goto</font> again;
00088           
00089       <font class="keywordflow">if</font> (chunk &lt; 0)
00090         {
00091           dbus_set_error (error,
00092                           DBUS_ERROR_SPAWN_FAILED,
00093                           <font class="stringliteral">"Failed to read from child pipe (%s)"</font>,
00094                           _dbus_strerror (errno));
00095 
00096           retval = READ_STATUS_ERROR;
00097           <font class="keywordflow">break</font>;
00098         }
00099       <font class="keywordflow">else</font> <font class="keywordflow">if</font> (chunk == 0)
00100         {
00101           retval = READ_STATUS_EOF;
00102           <font class="keywordflow">break</font>; <font class="comment">/* EOF */</font>
00103         }
00104       <font class="keywordflow">else</font> <font class="comment">/* chunk &gt; 0 */</font>
00105         bytes += chunk;
00106     }
00107 
00108   *n_ints_read = (int)(bytes / <font class="keyword">sizeof</font>(int));
00109 
00110   <font class="keywordflow">return</font> retval;
00111 }
00112 
00113 <font class="keyword">static</font> ReadStatus
00114 read_pid (<font class="keywordtype">int</font>        fd,
00115           pid_t     *buf,
00116           <a class="code" href="structDBusError.html">DBusError</a> *error)
00117 {
00118   size_t bytes = 0;    
00119   ReadStatus retval;
00120   
00121   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00122 
00123   retval = READ_STATUS_OK;
00124   
00125   <font class="keywordflow">while</font> (TRUE)
00126     {
00127       size_t chunk;    
00128       size_t to_read;
00129       
00130     again:
00131       to_read = <font class="keyword">sizeof</font> (pid_t) - bytes;
00132 
00133       <font class="keywordflow">if</font> (to_read == 0)
00134         <font class="keywordflow">break</font>;
00135       
00136       chunk = read (fd,
00137                     ((<font class="keywordtype">char</font>*)buf) + bytes,
00138                     to_read);
00139       <font class="keywordflow">if</font> (chunk &lt; 0 &amp;&amp; errno == EINTR)
00140         <font class="keywordflow">goto</font> again;
00141           
00142       <font class="keywordflow">if</font> (chunk &lt; 0)
00143         {
00144           dbus_set_error (error,
00145                           DBUS_ERROR_SPAWN_FAILED,
00146                           <font class="stringliteral">"Failed to read from child pipe (%s)"</font>,
00147                           _dbus_strerror (errno));
00148 
00149           retval = READ_STATUS_ERROR;
00150           <font class="keywordflow">break</font>;
00151         }
00152       <font class="keywordflow">else</font> <font class="keywordflow">if</font> (chunk == 0)
00153         {
00154           retval = READ_STATUS_EOF;
00155           <font class="keywordflow">break</font>; <font class="comment">/* EOF */</font>
00156         }
00157       <font class="keywordflow">else</font> <font class="comment">/* chunk &gt; 0 */</font>
00158         bytes += chunk;
00159     }
00160 
00161   <font class="keywordflow">return</font> retval;
00162 }
00163 
00164 <font class="comment">/* The implementation uses an intermediate child between the main process</font>
00165 <font class="comment"> * and the grandchild. The grandchild is our spawned process. The intermediate</font>
00166 <font class="comment"> * child is a babysitter process; it keeps track of when the grandchild</font>
00167 <font class="comment"> * exits/crashes, and reaps the grandchild.</font>
00168 <font class="comment"> */</font>
00169 
00170 <font class="comment">/* Messages from children to parents */</font>
00171 <font class="keyword">enum</font>
00172 {
00173   CHILD_EXITED,            <font class="comment">/* This message is followed by the exit status int */</font>
00174   CHILD_FORK_FAILED,       <font class="comment">/* Followed by errno */</font>
00175   CHILD_EXEC_FAILED,       <font class="comment">/* Followed by errno */</font>
00176   CHILD_PID                <font class="comment">/* Followed by pid_t */</font>
00177 };
00178 
<a name="l00182"></a><a class="code" href="structDBusBabysitter.html">00182</a> <font class="keyword">struct </font><a class="code" href="structDBusBabysitter.html">DBusBabysitter</a>
00183 {
<a name="l00184"></a><a class="code" href="structDBusBabysitter.html#m0">00184</a>   <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m0">refcount</a>; 
<a name="l00186"></a><a class="code" href="structDBusBabysitter.html#m1">00186</a>   <font class="keywordtype">char</font> *<a class="code" href="structDBusBabysitter.html#m1">executable</a>; 
<a name="l00188"></a><a class="code" href="structDBusBabysitter.html#m2">00188</a>   <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>; 
<a name="l00189"></a><a class="code" href="structDBusBabysitter.html#m3">00189</a>   <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>; 
<a name="l00191"></a><a class="code" href="structDBusBabysitter.html#m4">00191</a>   pid_t <a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a>;  
<a name="l00192"></a><a class="code" href="structDBusBabysitter.html#m5">00192</a>   pid_t <a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a>; 
<a name="l00194"></a><a class="code" href="structDBusBabysitter.html#m6">00194</a>   <a class="code" href="structDBusWatchList.html">DBusWatchList</a> *<a class="code" href="structDBusBabysitter.html#m6">watches</a>; 
<a name="l00196"></a><a class="code" href="structDBusBabysitter.html#m7">00196</a>   <a class="code" href="structDBusWatch.html">DBusWatch</a> *<a class="code" href="structDBusBabysitter.html#m7">error_watch</a>; 
<a name="l00197"></a><a class="code" href="structDBusBabysitter.html#m8">00197</a>   <a class="code" href="structDBusWatch.html">DBusWatch</a> *<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a>; 
<a name="l00199"></a><a class="code" href="structDBusBabysitter.html#m9">00199</a>   <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m9">errnum</a>; 
<a name="l00200"></a><a class="code" href="structDBusBabysitter.html#m10">00200</a>   <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m10">status</a>; 
<a name="l00201"></a><a class="code" href="structDBusBabysitter.html#m11">00201</a>   <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m11">have_child_status</a> : 1; 
<a name="l00202"></a><a class="code" href="structDBusBabysitter.html#m12">00202</a>   <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m12">have_fork_errnum</a> : 1; 
<a name="l00203"></a><a class="code" href="structDBusBabysitter.html#m13">00203</a>   <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font> <a class="code" href="structDBusBabysitter.html#m13">have_exec_errnum</a> : 1; 
00204 };
00205 
00206 <font class="keyword">static</font> <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a>*
00207 _dbus_babysitter_new (<font class="keywordtype">void</font>)
00208 {
00209   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter;
00210 
00211   sitter = dbus_new0 (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a>, 1);
00212   <font class="keywordflow">if</font> (sitter == NULL)
00213     <font class="keywordflow">return</font> NULL;
00214 
00215   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m0">refcount</a> = 1;
00216 
00217   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> = -1;
00218   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a> = -1;
00219   
00220   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a> = -1;
00221   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a> = -1;
00222 
00223   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a> = _dbus_watch_list_new ();
00224   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a> == NULL)
00225     <font class="keywordflow">goto</font> failed;
00226   
00227   <font class="keywordflow">return</font> sitter;
00228 
00229  failed:
00230   _dbus_babysitter_unref (sitter);
00231   <font class="keywordflow">return</font> NULL;
00232 }
00233 
00240 <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *
<a name="l00241"></a><a class="code" href="group__DBusInternalsUtils.html#a20">00241</a> _dbus_babysitter_ref (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
00242 {
00243   _dbus_assert (sitter != NULL);
00244   _dbus_assert (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m0">refcount</a> &gt; 0);
00245   
00246   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m0">refcount</a> += 1;
00247 
00248   <font class="keywordflow">return</font> sitter;
00249 }
00250 
00256 <font class="keywordtype">void</font>
<a name="l00257"></a><a class="code" href="group__DBusInternalsUtils.html#a21">00257</a> _dbus_babysitter_unref (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
00258 {
00259   _dbus_assert (sitter != NULL);
00260   _dbus_assert (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m0">refcount</a> &gt; 0);
00261   
00262   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m0">refcount</a> -= 1;
00263   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m0">refcount</a> == 0)
00264     {      
00265       <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> &gt;= 0)
00266         {
00267           close (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>);
00268           sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> = -1;
00269         }
00270 
00271       <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a> &gt;= 0)
00272         {
00273           close (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>);
00274           sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a> = -1;
00275         }
00276 
00277       <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a> != -1)
00278         {
00279           <font class="keywordtype">int</font> status;
00280           <font class="keywordtype">int</font> ret;
00281 
00282           <font class="comment">/* Reap the babysitter */</font>
00283         again:
00284           ret = waitpid (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a>, &amp;status, 0);
00285           <font class="keywordflow">if</font> (ret &lt; 0)
00286             {
00287               <font class="keywordflow">if</font> (errno == EINTR)
00288                 <font class="keywordflow">goto</font> again;
00289               <font class="keywordflow">else</font> <font class="keywordflow">if</font> (errno == ECHILD)
00290                 _dbus_warn (<font class="stringliteral">"Babysitter process not available to be reaped; should not happen\n"</font>);
00291               <font class="keywordflow">else</font>
00292                 _dbus_warn (<font class="stringliteral">"Unexpected error %d in waitpid() for babysitter: %s\n"</font>,
00293                             errno, _dbus_strerror (errno));
00294             }
00295           <font class="keywordflow">else</font>
00296             {
00297               _dbus_verbose (<font class="stringliteral">"Reaped %ld, waiting for babysitter %ld\n"</font>,
00298                              (<font class="keywordtype">long</font>) ret, (<font class="keywordtype">long</font>) sitter-&gt;<a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a>);
00299               
00300               <font class="keywordflow">if</font> (WIFEXITED (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>))
00301                 _dbus_verbose (<font class="stringliteral">"Babysitter exited with status %d\n"</font>,
00302                                WEXITSTATUS (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>));
00303               <font class="keywordflow">else</font> <font class="keywordflow">if</font> (WIFSIGNALED (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>))
00304                 _dbus_verbose (<font class="stringliteral">"Babysitter received signal %d\n"</font>,
00305                                WTERMSIG (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>));
00306               <font class="keywordflow">else</font>
00307                 _dbus_verbose (<font class="stringliteral">"Babysitter exited abnormally\n"</font>);
00308             }
00309 
00310           sitter-&gt;<a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a> = -1;
00311         }
00312       
00313       <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a>)
00314         {
00315           _dbus_watch_invalidate (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a>);
00316           _dbus_watch_unref (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a>);
00317           sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a> = NULL;
00318         }
00319 
00320       <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a>)
00321         {
00322           _dbus_watch_invalidate (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a>);
00323           _dbus_watch_unref (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a>);
00324           sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a> = NULL;
00325         }
00326       
00327       <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a>)
00328         _dbus_watch_list_free (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a>);
00329 
00330       dbus_free (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>);
00331       
00332       dbus_free (sitter);
00333     }
00334 }
00335 
00336 <font class="keyword">static</font> ReadStatus
00337 read_data (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter,
00338            <font class="keywordtype">int</font>             fd)
00339 {
00340   <font class="keywordtype">int</font> what;
00341   <font class="keywordtype">int</font> got;
00342   <a class="code" href="structDBusError.html">DBusError</a> error;
00343   ReadStatus r;
00344   
00345   dbus_error_init (&amp;error);
00346   
00347   r = read_ints (fd, &amp;what, 1, &amp;got, &amp;error);
00348 
00349   <font class="keywordflow">switch</font> (r)
00350     {
00351     <font class="keywordflow">case</font> READ_STATUS_ERROR:
00352       _dbus_warn (<font class="stringliteral">"Failed to read data from fd %d: %s\n"</font>, fd, error.<a class="code" href="structDBusError.html#m1">message</a>);
00353       dbus_error_free (&amp;error);
00354       <font class="keywordflow">return</font> r;
00355 
00356     <font class="keywordflow">case</font> READ_STATUS_EOF:
00357       <font class="keywordflow">return</font> r;
00358 
00359     <font class="keywordflow">case</font> READ_STATUS_OK:
00360       <font class="keywordflow">break</font>;
00361     }
00362   
00363   <font class="keywordflow">if</font> (got == 1)
00364     {
00365       <font class="keywordflow">switch</font> (what)
00366         {
00367         <font class="keywordflow">case</font> CHILD_EXITED:
00368         <font class="keywordflow">case</font> CHILD_FORK_FAILED:
00369         <font class="keywordflow">case</font> CHILD_EXEC_FAILED:
00370           {
00371             <font class="keywordtype">int</font> arg;
00372             
00373             r = read_ints (fd, &amp;arg, 1, &amp;got, &amp;error);
00374 
00375             <font class="keywordflow">switch</font> (r)
00376               {
00377               <font class="keywordflow">case</font> READ_STATUS_ERROR:
00378                 _dbus_warn (<font class="stringliteral">"Failed to read arg from fd %d: %s\n"</font>, fd, error.<a class="code" href="structDBusError.html#m1">message</a>);
00379                 dbus_error_free (&amp;error);
00380                 <font class="keywordflow">return</font> r;
00381               <font class="keywordflow">case</font> READ_STATUS_EOF:
00382                 <font class="keywordflow">return</font> r;
00383               <font class="keywordflow">case</font> READ_STATUS_OK:
00384                 <font class="keywordflow">break</font>;
00385               }
00386             
00387             <font class="keywordflow">if</font> (got == 1)
00388               {
00389                 <font class="keywordflow">if</font> (what == CHILD_EXITED)
00390                   {
00391                     sitter-&gt;<a class="code" href="structDBusBabysitter.html#m11">have_child_status</a> = TRUE;
00392                     sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a> = arg;
00393                     _dbus_verbose (<font class="stringliteral">"recorded child status exited = %d signaled = %d exitstatus = %d termsig = %d\n"</font>,
00394                                    WIFEXITED (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>), WIFSIGNALED (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>),
00395                                    WEXITSTATUS (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>), WTERMSIG (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>));
00396                   }
00397                 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (what == CHILD_FORK_FAILED)
00398                   {
00399                     sitter-&gt;<a class="code" href="structDBusBabysitter.html#m12">have_fork_errnum</a> = TRUE;
00400                     sitter-&gt;<a class="code" href="structDBusBabysitter.html#m9">errnum</a> = arg;
00401                     _dbus_verbose (<font class="stringliteral">"recorded fork errnum %d\n"</font>, sitter-&gt;<a class="code" href="structDBusBabysitter.html#m9">errnum</a>);
00402                   }
00403                 <font class="keywordflow">else</font> <font class="keywordflow">if</font> (what == CHILD_EXEC_FAILED)
00404                   {
00405                     sitter-&gt;<a class="code" href="structDBusBabysitter.html#m13">have_exec_errnum</a> = TRUE;
00406                     sitter-&gt;<a class="code" href="structDBusBabysitter.html#m9">errnum</a> = arg;
00407                     _dbus_verbose (<font class="stringliteral">"recorded exec errnum %d\n"</font>, sitter-&gt;<a class="code" href="structDBusBabysitter.html#m9">errnum</a>);
00408                   }
00409               }
00410           }
00411           <font class="keywordflow">break</font>;
00412         <font class="keywordflow">case</font> CHILD_PID:
00413           {
00414             pid_t pid = -1;
00415 
00416             r = read_pid (fd, &amp;pid, &amp;error);
00417             
00418             <font class="keywordflow">switch</font> (r)
00419               {
00420               <font class="keywordflow">case</font> READ_STATUS_ERROR:
00421                 _dbus_warn (<font class="stringliteral">"Failed to read PID from fd %d: %s\n"</font>, fd, error.<a class="code" href="structDBusError.html#m1">message</a>);
00422                 dbus_error_free (&amp;error);
00423                 <font class="keywordflow">return</font> r;
00424               <font class="keywordflow">case</font> READ_STATUS_EOF:
00425                 <font class="keywordflow">return</font> r;
00426               <font class="keywordflow">case</font> READ_STATUS_OK:
00427                 <font class="keywordflow">break</font>;
00428               }
00429             
00430             sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a> = pid;
00431             
00432             _dbus_verbose (<font class="stringliteral">"recorded grandchild pid %d\n"</font>, sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a>);
00433           }
00434           <font class="keywordflow">break</font>;
00435         <font class="keywordflow">default</font>:
00436           _dbus_warn (<font class="stringliteral">"Unknown message received from babysitter process\n"</font>);
00437           <font class="keywordflow">break</font>;
00438         }
00439     }
00440 
00441   <font class="keywordflow">return</font> r;
00442 }
00443 
00444 <font class="keyword">static</font> <font class="keywordtype">void</font>
00445 close_socket_to_babysitter (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
00446 {
00447   _dbus_verbose (<font class="stringliteral">"Closing babysitter\n"</font>);
00448   close (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>);
00449   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> = -1;
00450 }
00451 
00452 <font class="keyword">static</font> <font class="keywordtype">void</font>
00453 close_error_pipe_from_child (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
00454 {
00455   _dbus_verbose (<font class="stringliteral">"Closing child error\n"</font>);
00456   close (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>);
00457   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a> = -1;
00458 }
00459 
00460 <font class="keyword">static</font> <font class="keywordtype">void</font>
00461 handle_babysitter_socket (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter,
00462                           <font class="keywordtype">int</font>             revents)
00463 {
00464   <font class="comment">/* Even if we have POLLHUP, we want to keep reading</font>
00465 <font class="comment">   * data until POLLIN goes away; so this function only</font>
00466 <font class="comment">   * looks at HUP/ERR if no IN is set.</font>
00467 <font class="comment">   */</font>
00468   <font class="keywordflow">if</font> (revents &amp; _DBUS_POLLIN)
00469     {
00470       _dbus_verbose (<font class="stringliteral">"Reading data from babysitter\n"</font>);
00471       <font class="keywordflow">if</font> (read_data (sitter, sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>) != READ_STATUS_OK)
00472         close_socket_to_babysitter (sitter);
00473     }
00474   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (revents &amp; (_DBUS_POLLERR | _DBUS_POLLHUP))
00475     {
00476       close_socket_to_babysitter (sitter);
00477     }
00478 }
00479 
00480 <font class="keyword">static</font> <font class="keywordtype">void</font>
00481 handle_error_pipe (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter,
00482                    <font class="keywordtype">int</font>             revents)
00483 {
00484   <font class="keywordflow">if</font> (revents &amp; _DBUS_POLLIN)
00485     {
00486       _dbus_verbose (<font class="stringliteral">"Reading data from child error\n"</font>);
00487       <font class="keywordflow">if</font> (read_data (sitter, sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>) != READ_STATUS_OK)
00488         close_error_pipe_from_child (sitter);
00489     }
00490   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (revents &amp; (_DBUS_POLLERR | _DBUS_POLLHUP))
00491     {
00492       close_error_pipe_from_child (sitter);
00493     }
00494 }
00495 
00496 <font class="comment">/* returns whether there were any poll events handled */</font>
00497 <font class="keyword">static</font> dbus_bool_t
00498 babysitter_iteration (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter,
00499                       dbus_bool_t     block)
00500 {
00501   <a class="code" href="structDBusPollFD.html">DBusPollFD</a> fds[2];
00502   <font class="keywordtype">int</font> i;
00503   dbus_bool_t descriptors_ready;
00504 
00505   descriptors_ready = FALSE;
00506   
00507   i = 0;
00508 
00509   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a> &gt;= 0)
00510     {
00511       fds[i].<a class="code" href="structDBusPollFD.html#m0">fd</a> = sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>;
00512       fds[i].<a class="code" href="structDBusPollFD.html#m1">events</a> = _DBUS_POLLIN;
00513       fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> = 0;
00514       ++i;
00515     }
00516   
00517   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> &gt;= 0)
00518     {
00519       fds[i].<a class="code" href="structDBusPollFD.html#m0">fd</a> = sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>;
00520       fds[i].<a class="code" href="structDBusPollFD.html#m1">events</a> = _DBUS_POLLIN;
00521       fds[i].<a class="code" href="structDBusPollFD.html#m2">revents</a> = 0;
00522       ++i;
00523     }
00524 
00525   <font class="keywordflow">if</font> (i &gt; 0)
00526     {
00527       <font class="keywordtype">int</font> ret;
00528 
00529       ret = _dbus_poll (fds, i, 0);
00530       <font class="keywordflow">if</font> (ret == 0 &amp;&amp; block)
00531         ret = _dbus_poll (fds, i, -1);
00532       
00533       <font class="keywordflow">if</font> (ret &gt; 0)
00534         {
00535           descriptors_ready = TRUE;
00536           
00537           <font class="keywordflow">while</font> (i &gt; 0)
00538             {
00539               --i;
00540               <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m0">fd</a> == sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>)
00541                 handle_error_pipe (sitter, fds[i].revents);
00542               <font class="keywordflow">else</font> <font class="keywordflow">if</font> (fds[i].<a class="code" href="structDBusPollFD.html#m0">fd</a> == sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>)
00543                 handle_babysitter_socket (sitter, fds[i].revents);
00544             }
00545         }
00546     }
00547 
00548   <font class="keywordflow">return</font> descriptors_ready;
00549 }
00550 
<a name="l00555"></a><a class="code" href="group__DBusInternalsUtils.html#a144">00555</a> <font class="preprocessor">#define LIVE_CHILDREN(sitter) ((sitter)-&gt;socket_to_babysitter &gt;= 0 || (sitter)-&gt;error_pipe_from_child &gt;= 0)</font>
00556 <font class="preprocessor"></font>
00563 <font class="keywordtype">void</font>
<a name="l00564"></a><a class="code" href="group__DBusInternalsUtils.html#a28">00564</a> _dbus_babysitter_kill_child (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
00565 {
00566   <font class="comment">/* be sure we have the PID of the child */</font>
00567   <font class="keywordflow">while</font> (LIVE_CHILDREN (sitter) &amp;&amp;
00568          sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a> == -1)
00569     babysitter_iteration (sitter, TRUE);
00570 
00571   _dbus_verbose (<font class="stringliteral">"Got child PID %ld for killing\n"</font>,
00572                  (<font class="keywordtype">long</font>) sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a>);
00573   
00574   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a> == -1)
00575     <font class="keywordflow">return</font>; <font class="comment">/* child is already dead, or we're so hosed we'll never recover */</font>
00576 
00577   kill (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m5">grandchild_pid</a>, SIGKILL);
00578 }
00579 
00585 dbus_bool_t
<a name="l00586"></a><a class="code" href="group__DBusInternalsUtils.html#a29">00586</a> _dbus_babysitter_get_child_exited (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
00587 {
00588 
00589   <font class="comment">/* Be sure we're up-to-date */</font>
00590   <font class="keywordflow">while</font> (LIVE_CHILDREN (sitter) &amp;&amp;
00591          babysitter_iteration (sitter, FALSE))
00592     ;
00593 
00594   <font class="comment">/* We will have exited the babysitter when the child has exited */</font>
00595   <font class="keywordflow">return</font> sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> &lt; 0;
00596 }
00597 
00607 <font class="keywordtype">void</font>
<a name="l00608"></a><a class="code" href="group__DBusInternalsUtils.html#a30">00608</a> _dbus_babysitter_set_child_exit_error (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter,
00609                                        <a class="code" href="structDBusError.html">DBusError</a>      *error)
00610 {
00611   <font class="keywordflow">if</font> (!_dbus_babysitter_get_child_exited (sitter))
00612     <font class="keywordflow">return</font>;
00613 
00614   <font class="comment">/* Note that if exec fails, we will also get a child status</font>
00615 <font class="comment">   * from the babysitter saying the child exited,</font>
00616 <font class="comment">   * so we need to give priority to the exec error</font>
00617 <font class="comment">   */</font>
00618   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m13">have_exec_errnum</a>)
00619     {
00620       dbus_set_error (error, DBUS_ERROR_SPAWN_EXEC_FAILED,
00621                       <font class="stringliteral">"Failed to execute program %s: %s"</font>,
00622                       sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>, _dbus_strerror (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m9">errnum</a>));
00623     }
00624   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m12">have_fork_errnum</a>)
00625     {
00626       dbus_set_error (error, DBUS_ERROR_NO_MEMORY,
00627                       <font class="stringliteral">"Failed to fork a new process %s: %s"</font>,
00628                       sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>, _dbus_strerror (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m9">errnum</a>));
00629     }
00630   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m11">have_child_status</a>)
00631     {
00632       <font class="keywordflow">if</font> (WIFEXITED (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>))
00633         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_EXITED,
00634                         <font class="stringliteral">"Process %s exited with status %d"</font>,
00635                         sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>, WEXITSTATUS (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>));
00636       <font class="keywordflow">else</font> <font class="keywordflow">if</font> (WIFSIGNALED (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>))
00637         dbus_set_error (error, DBUS_ERROR_SPAWN_CHILD_SIGNALED,
00638                         <font class="stringliteral">"Process %s received signal %d"</font>,
00639                         sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>, WTERMSIG (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m10">status</a>));
00640       <font class="keywordflow">else</font>
00641         dbus_set_error (error, DBUS_ERROR_FAILED,
00642                         <font class="stringliteral">"Process %s exited abnormally"</font>,
00643                         sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>);
00644     }
00645   <font class="keywordflow">else</font>
00646     {
00647       dbus_set_error (error, DBUS_ERROR_FAILED,
00648                       <font class="stringliteral">"Process %s exited, reason unknown"</font>,
00649                       sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a>);
00650     }
00651 }
00652 
00665 dbus_bool_t
<a name="l00666"></a><a class="code" href="group__DBusInternalsUtils.html#a31">00666</a> _dbus_babysitter_set_watch_functions (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a>            *sitter,
00667                                       DBusAddWatchFunction       add_function,
00668                                       DBusRemoveWatchFunction    remove_function,
00669                                       DBusWatchToggledFunction   toggled_function,
00670                                       <font class="keywordtype">void</font>                      *data,
00671                                       DBusFreeFunction           free_data_function)
00672 {
00673   <font class="keywordflow">return</font> _dbus_watch_list_set_functions (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a>,
00674                                          add_function,
00675                                          remove_function,
00676                                          toggled_function,
00677                                          data,
00678                                          free_data_function);
00679 }
00680 
00681 <font class="keyword">static</font> dbus_bool_t
00682 handle_watch (<a class="code" href="structDBusWatch.html">DBusWatch</a>       *watch,
00683               <font class="keywordtype">unsigned</font> <font class="keywordtype">int</font>     condition,
00684               <font class="keywordtype">void</font>            *data)
00685 {
00686   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter = data;
00687   <font class="keywordtype">int</font> revents;
00688   <font class="keywordtype">int</font> fd;
00689   
00690   revents = 0;
00691   <font class="keywordflow">if</font> (condition &amp; DBUS_WATCH_READABLE)
00692     revents |= _DBUS_POLLIN;
00693   <font class="keywordflow">if</font> (condition &amp; DBUS_WATCH_ERROR)
00694     revents |= _DBUS_POLLERR;
00695   <font class="keywordflow">if</font> (condition &amp; DBUS_WATCH_HANGUP)
00696     revents |= _DBUS_POLLHUP;
00697 
00698   fd = dbus_watch_get_fd (watch);
00699 
00700   <font class="keywordflow">if</font> (fd == sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a>)
00701     handle_error_pipe (sitter, revents);
00702   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (fd == sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a>)
00703     handle_babysitter_socket (sitter, revents);
00704 
00705   <font class="keywordflow">while</font> (LIVE_CHILDREN (sitter) &amp;&amp;
00706          babysitter_iteration (sitter, FALSE))
00707     ;
00708   
00709   <font class="keywordflow">return</font> TRUE;
00710 }
00711 
<a name="l00713"></a><a class="code" href="group__DBusInternalsUtils.html#a145">00713</a> <font class="preprocessor">#define READ_END 0</font>
00714 <font class="preprocessor"></font>
<a name="l00715"></a><a class="code" href="group__DBusInternalsUtils.html#a146">00715</a> <font class="preprocessor">#define WRITE_END 1</font>
00716 <font class="preprocessor"></font>
00717 
00718 <font class="comment">/* Avoids a danger in threaded situations (calling close()</font>
00719 <font class="comment"> * on a file descriptor twice, and another thread has</font>
00720 <font class="comment"> * re-opened it since the first close)</font>
00721 <font class="comment"> */</font>
00722 <font class="keyword">static</font> <font class="keywordtype">int</font>
00723 close_and_invalidate (<font class="keywordtype">int</font> *fd)
00724 {
00725   <font class="keywordtype">int</font> ret;
00726 
00727   <font class="keywordflow">if</font> (*fd &lt; 0)
00728     <font class="keywordflow">return</font> -1;
00729   <font class="keywordflow">else</font>
00730     {
00731       ret = close (*fd);
00732       *fd = -1;
00733     }
00734 
00735   <font class="keywordflow">return</font> ret;
00736 }
00737 
00738 <font class="keyword">static</font> dbus_bool_t
00739 make_pipe (<font class="keywordtype">int</font>         p[2],
00740            <a class="code" href="structDBusError.html">DBusError</a>  *error)
00741 {
00742   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00743   
00744   <font class="keywordflow">if</font> (pipe (p) &lt; 0)
00745     {
00746       dbus_set_error (error,
00747                       DBUS_ERROR_SPAWN_FAILED,
00748                       <font class="stringliteral">"Failed to create pipe for communicating with child process (%s)"</font>,
00749                       _dbus_strerror (errno));
00750       <font class="keywordflow">return</font> FALSE;
00751     }
00752 
00753   <font class="keywordflow">return</font> TRUE;
00754 }
00755 
00756 <font class="keyword">static</font> <font class="keywordtype">void</font>
00757 do_write (<font class="keywordtype">int</font> fd, <font class="keyword">const</font> <font class="keywordtype">void</font> *buf, size_t count)
00758 {
00759   size_t bytes_written;
00760   <font class="keywordtype">int</font> ret;
00761   
00762   bytes_written = 0;
00763   
00764  again:
00765   
00766   ret = write (fd, ((<font class="keyword">const</font> <font class="keywordtype">char</font>*)buf) + bytes_written, count - bytes_written);
00767 
00768   <font class="keywordflow">if</font> (ret &lt; 0)
00769     {
00770       <font class="keywordflow">if</font> (errno == EINTR)
00771         <font class="keywordflow">goto</font> again;
00772       <font class="keywordflow">else</font>
00773         {
00774           _dbus_warn (<font class="stringliteral">"Failed to write data to pipe!\n"</font>);
00775           exit (1); <font class="comment">/* give up, we suck */</font>
00776         }
00777     }
00778   <font class="keywordflow">else</font>
00779     bytes_written += ret;
00780   
00781   <font class="keywordflow">if</font> (bytes_written &lt; count)
00782     <font class="keywordflow">goto</font> again;
00783 }
00784 
00785 <font class="keyword">static</font> <font class="keywordtype">void</font>
00786 write_err_and_exit (<font class="keywordtype">int</font> fd, <font class="keywordtype">int</font> msg)
00787 {
00788   <font class="keywordtype">int</font> en = errno;
00789 
00790   do_write (fd, &amp;msg, <font class="keyword">sizeof</font> (msg));
00791   do_write (fd, &amp;en, <font class="keyword">sizeof</font> (en));
00792   
00793   exit (1);
00794 }
00795 
00796 <font class="keyword">static</font> <font class="keywordtype">void</font>
00797 write_pid (<font class="keywordtype">int</font> fd, pid_t pid)
00798 {
00799   <font class="keywordtype">int</font> msg = CHILD_PID;
00800   
00801   do_write (fd, &amp;msg, <font class="keyword">sizeof</font> (msg));
00802   do_write (fd, &amp;pid, <font class="keyword">sizeof</font> (pid));
00803 }
00804 
00805 <font class="keyword">static</font> <font class="keywordtype">void</font>
00806 write_status_and_exit (<font class="keywordtype">int</font> fd, <font class="keywordtype">int</font> status)
00807 {
00808   <font class="keywordtype">int</font> msg = CHILD_EXITED;
00809   
00810   do_write (fd, &amp;msg, <font class="keyword">sizeof</font> (msg));
00811   do_write (fd, &amp;status, <font class="keyword">sizeof</font> (status));
00812   
00813   exit (0);
00814 }
00815 
00816 <font class="keyword">static</font> <font class="keywordtype">void</font>
00817 do_exec (<font class="keywordtype">int</font>                       child_err_report_fd,
00818          <font class="keywordtype">char</font>                    **argv,
00819          DBusSpawnChildSetupFunc   child_setup,
00820          <font class="keywordtype">void</font>                     *user_data)
00821 {
00822 <font class="preprocessor">#ifdef DBUS_BUILD_TESTS</font>
00823 <font class="preprocessor"></font>  <font class="keywordtype">int</font> i, max_open;
00824 <font class="preprocessor">#endif</font>
00825 <font class="preprocessor"></font>
00826   _dbus_verbose_reset ();
00827   _dbus_verbose (<font class="stringliteral">"Child process has PID %lu\n"</font>,
00828                  _dbus_getpid ());
00829   
00830   <font class="keywordflow">if</font> (child_setup)
00831     (* child_setup) (user_data);
00832 
00833 <font class="preprocessor">#ifdef DBUS_BUILD_TESTS</font>
00834 <font class="preprocessor"></font>  max_open = sysconf (_SC_OPEN_MAX);
00835   
00836   <font class="keywordflow">for</font> (i = 3; i &lt; max_open; i++)
00837     {
00838       <font class="keywordtype">int</font> retval;
00839 
00840       <font class="keywordflow">if</font> (i == child_err_report_fd)
00841         <font class="keywordflow">continue</font>;
00842       
00843       retval = fcntl (i, F_GETFD);
00844 
00845       <font class="keywordflow">if</font> (retval != -1 &amp;&amp; !(retval &amp; FD_CLOEXEC))
00846         _dbus_warn (<font class="stringliteral">"Fd %d did not have the close-on-exec flag set!\n"</font>, i);
00847     }
00848 <font class="preprocessor">#endif</font>
00849 <font class="preprocessor"></font>  
00850   execv (argv[0], argv);
00851   
00852   <font class="comment">/* Exec failed */</font>
00853   write_err_and_exit (child_err_report_fd,
00854                       CHILD_EXEC_FAILED);
00855 }
00856 
00857 <font class="keyword">static</font> <font class="keywordtype">void</font>
00858 check_babysit_events (pid_t grandchild_pid,
00859                       <font class="keywordtype">int</font>   parent_pipe,
00860                       <font class="keywordtype">int</font>   revents)
00861 {
00862   pid_t ret;
00863   <font class="keywordtype">int</font> status;
00864   
00865   ret = waitpid (grandchild_pid, &amp;status, WNOHANG);
00866 
00867   <font class="keywordflow">if</font> (ret == 0)
00868     {
00869       _dbus_verbose (<font class="stringliteral">"no child exited\n"</font>);
00870       
00871       ; <font class="comment">/* no child exited */</font>
00872     }
00873   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (ret &lt; 0)
00874     {
00875       <font class="comment">/* This isn't supposed to happen. */</font>
00876       _dbus_warn (<font class="stringliteral">"unexpected waitpid() failure in check_babysit_events(): %s\n"</font>,
00877                   _dbus_strerror (errno));
00878       exit (1);
00879     }
00880   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (ret == grandchild_pid)
00881     {
00882       <font class="comment">/* Child exited */</font>
00883       _dbus_verbose (<font class="stringliteral">"reaped child pid %ld\n"</font>, (<font class="keywordtype">long</font>) ret);
00884       
00885       write_status_and_exit (parent_pipe, status);
00886     }
00887   <font class="keywordflow">else</font>
00888     {
00889       _dbus_warn (<font class="stringliteral">"waitpid() reaped pid %d that we've never heard of\n"</font>,
00890                   (<font class="keywordtype">int</font>) ret);
00891       exit (1);
00892     }
00893 
00894   <font class="keywordflow">if</font> (revents &amp; _DBUS_POLLIN)
00895     {
00896       _dbus_verbose (<font class="stringliteral">"babysitter got POLLIN from parent pipe\n"</font>);
00897     }
00898 
00899   <font class="keywordflow">if</font> (revents &amp; (_DBUS_POLLERR | _DBUS_POLLHUP))
00900     {
00901       <font class="comment">/* Parent is gone, so we just exit */</font>
00902       _dbus_verbose (<font class="stringliteral">"babysitter got POLLERR or POLLHUP from parent\n"</font>);
00903       exit (0);
00904     }
00905 }
00906 
00907 <font class="keyword">static</font> <font class="keywordtype">int</font> babysit_sigchld_pipe = -1;
00908 
00909 <font class="keyword">static</font> <font class="keywordtype">void</font>
00910 babysit_signal_handler (<font class="keywordtype">int</font> signo)
00911 {
00912   <font class="keywordtype">char</font> b = <font class="charliteral">'\0'</font>;
00913  again:
00914   write (babysit_sigchld_pipe, &amp;b, 1);
00915   <font class="keywordflow">if</font> (errno == EINTR)
00916     <font class="keywordflow">goto</font> again;
00917 }
00918 
00919 <font class="keyword">static</font> <font class="keywordtype">void</font>
00920 babysit (pid_t grandchild_pid,
00921          <font class="keywordtype">int</font>   parent_pipe)
00922 {
00923   <font class="keywordtype">int</font> sigchld_pipe[2];
00924 
00925   <font class="comment">/* We don't exec, so we keep parent state, such as the pid that</font>
00926 <font class="comment">   * _dbus_verbose() uses. Reset the pid here.</font>
00927 <font class="comment">   */</font>
00928   _dbus_verbose_reset ();
00929   
00930   <font class="comment">/* I thought SIGCHLD would just wake up the poll, but</font>
00931 <font class="comment">   * that didn't seem to work, so added this pipe.</font>
00932 <font class="comment">   * Probably the pipe is more likely to work on busted</font>
00933 <font class="comment">   * operating systems anyhow.</font>
00934 <font class="comment">   */</font>
00935   <font class="keywordflow">if</font> (pipe (sigchld_pipe) &lt; 0)
00936     {
00937       _dbus_warn (<font class="stringliteral">"Not enough file descriptors to create pipe in babysitter process\n"</font>);
00938       exit (1);
00939     }
00940 
00941   babysit_sigchld_pipe = sigchld_pipe[WRITE_END];
00942 
00943   _dbus_set_signal_handler (SIGCHLD, babysit_signal_handler);
00944   
00945   write_pid (parent_pipe, grandchild_pid);
00946 
00947   check_babysit_events (grandchild_pid, parent_pipe, 0);
00948 
00949   <font class="keywordflow">while</font> (TRUE)
00950     {
00951       <a class="code" href="structDBusPollFD.html">DBusPollFD</a> pfds[2];
00952       
00953       pfds[0].<a class="code" href="structDBusPollFD.html#m0">fd</a> = parent_pipe;
00954       pfds[0].<a class="code" href="structDBusPollFD.html#m1">events</a> = _DBUS_POLLIN;
00955       pfds[0].<a class="code" href="structDBusPollFD.html#m2">revents</a> = 0;
00956 
00957       pfds[1].<a class="code" href="structDBusPollFD.html#m0">fd</a> = sigchld_pipe[READ_END];
00958       pfds[1].<a class="code" href="structDBusPollFD.html#m1">events</a> = _DBUS_POLLIN;
00959       pfds[1].<a class="code" href="structDBusPollFD.html#m2">revents</a> = 0;
00960       
00961       _dbus_poll (pfds, _DBUS_N_ELEMENTS (pfds), -1);
00962 
00963       <font class="keywordflow">if</font> (pfds[0].<a class="code" href="structDBusPollFD.html#m2">revents</a> != 0)
00964         {
00965           check_babysit_events (grandchild_pid, parent_pipe, pfds[0].revents);
00966         }
00967       <font class="keywordflow">else</font> <font class="keywordflow">if</font> (pfds[1].<a class="code" href="structDBusPollFD.html#m2">revents</a> &amp; _DBUS_POLLIN)
00968         {
00969           <font class="keywordtype">char</font> b;
00970           read (sigchld_pipe[READ_END], &amp;b, 1);
00971           <font class="comment">/* do waitpid check */</font>
00972           check_babysit_events (grandchild_pid, parent_pipe, 0);
00973         }
00974     }
00975   
00976   exit (1);
00977 }
00978 
00997 dbus_bool_t
<a name="l00998"></a><a class="code" href="group__DBusInternalsUtils.html#a43">00998</a> _dbus_spawn_async_with_babysitter (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a>          **sitter_p,
00999                                    <font class="keywordtype">char</font>                    **argv,
01000                                    DBusSpawnChildSetupFunc   child_setup,
01001                                    <font class="keywordtype">void</font>                     *user_data,
01002                                    <a class="code" href="structDBusError.html">DBusError</a>                *error)
01003 {
01004   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter;
01005   <font class="keywordtype">int</font> child_err_report_pipe[2] = { -1, -1 };
01006   <font class="keywordtype">int</font> babysitter_pipe[2] = { -1, -1 };
01007   pid_t pid;
01008   
01009   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01010 
01011   *sitter_p = NULL;
01012   sitter = NULL;
01013 
01014   sitter = _dbus_babysitter_new ();
01015   <font class="keywordflow">if</font> (sitter == NULL)
01016     {
01017       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01018       <font class="keywordflow">return</font> FALSE;
01019     }
01020 
01021   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a> = _dbus_strdup (argv[0]);
01022   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m1">executable</a> == NULL)
01023     {
01024       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01025       <font class="keywordflow">goto</font> cleanup_and_fail;
01026     }
01027   
01028   <font class="keywordflow">if</font> (!make_pipe (child_err_report_pipe, error))
01029     <font class="keywordflow">goto</font> cleanup_and_fail;
01030 
01031   _dbus_fd_set_close_on_exec (child_err_report_pipe[READ_END]);
01032   
01033   <font class="keywordflow">if</font> (!_dbus_full_duplex_pipe (&amp;babysitter_pipe[0], &amp;babysitter_pipe[1], TRUE, error))
01034     <font class="keywordflow">goto</font> cleanup_and_fail;
01035 
01036   _dbus_fd_set_close_on_exec (babysitter_pipe[0]);
01037   _dbus_fd_set_close_on_exec (babysitter_pipe[1]);
01038 
01039   <font class="comment">/* Setting up the babysitter is only useful in the parent,</font>
01040 <font class="comment">   * but we don't want to run out of memory and fail</font>
01041 <font class="comment">   * after we've already forked, since then we'd leak</font>
01042 <font class="comment">   * child processes everywhere.</font>
01043 <font class="comment">   */</font>
01044   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a> = _dbus_watch_new (child_err_report_pipe[READ_END],
01045                                          DBUS_WATCH_READABLE,
01046                                          TRUE, handle_watch, sitter, NULL);
01047   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a> == NULL)
01048     {
01049       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01050       <font class="keywordflow">goto</font> cleanup_and_fail;
01051     }
01052         
01053   <font class="keywordflow">if</font> (!_dbus_watch_list_add_watch (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a>,  sitter-&gt;<a class="code" href="structDBusBabysitter.html#m7">error_watch</a>))
01054     {
01055       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01056       <font class="keywordflow">goto</font> cleanup_and_fail;
01057     }
01058       
01059   sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a> = _dbus_watch_new (babysitter_pipe[0],
01060                                           DBUS_WATCH_READABLE,
01061                                           TRUE, handle_watch, sitter, NULL);
01062   <font class="keywordflow">if</font> (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a> == NULL)
01063     {
01064       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01065       <font class="keywordflow">goto</font> cleanup_and_fail;
01066     }
01067       
01068   <font class="keywordflow">if</font> (!_dbus_watch_list_add_watch (sitter-&gt;<a class="code" href="structDBusBabysitter.html#m6">watches</a>,  sitter-&gt;<a class="code" href="structDBusBabysitter.html#m8">sitter_watch</a>))
01069     {
01070       dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
01071       <font class="keywordflow">goto</font> cleanup_and_fail;
01072     }
01073 
01074   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01075   
01076   pid = fork ();
01077   
01078   <font class="keywordflow">if</font> (pid &lt; 0)
01079     {
01080       dbus_set_error (error,
01081                       DBUS_ERROR_SPAWN_FORK_FAILED,
01082                       <font class="stringliteral">"Failed to fork (%s)"</font>,
01083                       _dbus_strerror (errno));
01084       <font class="keywordflow">goto</font> cleanup_and_fail;
01085     }
01086   <font class="keywordflow">else</font> <font class="keywordflow">if</font> (pid == 0)
01087     {
01088       <font class="comment">/* Immediate child, this is the babysitter process. */</font>
01089       <font class="keywordtype">int</font> grandchild_pid;
01090       
01091       <font class="comment">/* Be sure we crash if the parent exits</font>
01092 <font class="comment">       * and we write to the err_report_pipe</font>
01093 <font class="comment">       */</font>
01094       signal (SIGPIPE, SIG_DFL);
01095 
01096       <font class="comment">/* Close the parent's end of the pipes. */</font>
01097       close_and_invalidate (&amp;child_err_report_pipe[READ_END]);
01098       close_and_invalidate (&amp;babysitter_pipe[0]);
01099       
01100       <font class="comment">/* Create the child that will exec () */</font>
01101       grandchild_pid = fork ();
01102       
01103       <font class="keywordflow">if</font> (grandchild_pid &lt; 0)
01104         {
01105           write_err_and_exit (babysitter_pipe[1],
01106                               CHILD_FORK_FAILED);
01107           _dbus_assert_not_reached (<font class="stringliteral">"Got to code after write_err_and_exit()"</font>);
01108         }
01109       <font class="keywordflow">else</font> <font class="keywordflow">if</font> (grandchild_pid == 0)
01110         {
01111           do_exec (child_err_report_pipe[WRITE_END],
01112                    argv,
01113                    child_setup, user_data);
01114           _dbus_assert_not_reached (<font class="stringliteral">"Got to code after exec() - should have exited on error"</font>);
01115         }
01116       <font class="keywordflow">else</font>
01117         {
01118           babysit (grandchild_pid, babysitter_pipe[1]);
01119           _dbus_assert_not_reached (<font class="stringliteral">"Got to code after babysit()"</font>);
01120         }
01121     }
01122   <font class="keywordflow">else</font>
01123     {      
01124       <font class="comment">/* Close the uncared-about ends of the pipes */</font>
01125       close_and_invalidate (&amp;child_err_report_pipe[WRITE_END]);
01126       close_and_invalidate (&amp;babysitter_pipe[1]);
01127 
01128       sitter-&gt;<a class="code" href="structDBusBabysitter.html#m2">socket_to_babysitter</a> = babysitter_pipe[0];
01129       babysitter_pipe[0] = -1;
01130       
01131       sitter-&gt;<a class="code" href="structDBusBabysitter.html#m3">error_pipe_from_child</a> = child_err_report_pipe[READ_END];
01132       child_err_report_pipe[READ_END] = -1;
01133 
01134       sitter-&gt;<a class="code" href="structDBusBabysitter.html#m4">sitter_pid</a> = pid;
01135 
01136       <font class="keywordflow">if</font> (sitter_p != NULL)
01137         *sitter_p = sitter;
01138       <font class="keywordflow">else</font>
01139         _dbus_babysitter_unref (sitter);
01140 
01141       _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01142       
01143       <font class="keywordflow">return</font> TRUE;
01144     }
01145 
01146  cleanup_and_fail:
01147 
01148   _DBUS_ASSERT_ERROR_IS_SET (error);
01149   
01150   close_and_invalidate (&amp;child_err_report_pipe[READ_END]);
01151   close_and_invalidate (&amp;child_err_report_pipe[WRITE_END]);
01152   close_and_invalidate (&amp;babysitter_pipe[0]);
01153   close_and_invalidate (&amp;babysitter_pipe[1]);
01154 
01155   <font class="keywordflow">if</font> (sitter != NULL)
01156     _dbus_babysitter_unref (sitter);
01157   
01158   <font class="keywordflow">return</font> FALSE;
01159 }
01160 
01163 <font class="preprocessor">#ifdef DBUS_BUILD_TESTS</font>
01164 <font class="preprocessor"></font>
01165 <font class="keyword">static</font> <font class="keywordtype">void</font>
01166 _dbus_babysitter_block_for_child_exit (<a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter)
01167 {
01168   <font class="keywordflow">while</font> (LIVE_CHILDREN (sitter))
01169     babysitter_iteration (sitter, TRUE);
01170 }
01171 
01172 <font class="keyword">static</font> dbus_bool_t
01173 check_spawn_nonexistent (<font class="keywordtype">void</font> *data)
01174 {
01175   <font class="keywordtype">char</font> *argv[4] = { NULL, NULL, NULL, NULL };
01176   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter;
01177   <a class="code" href="structDBusError.html">DBusError</a> error;
01178   
01179   sitter = NULL;
01180   
01181   dbus_error_init (&amp;error);
01182 
01183   <font class="comment">/*** Test launching nonexistent binary */</font>
01184   
01185   argv[0] = <font class="stringliteral">"/this/does/not/exist/32542sdgafgafdg"</font>;
01186   <font class="keywordflow">if</font> (_dbus_spawn_async_with_babysitter (&amp;sitter, argv,
01187                                          NULL, NULL,
01188                                          &amp;error))
01189     {
01190       _dbus_babysitter_block_for_child_exit (sitter);
01191       _dbus_babysitter_set_child_exit_error (sitter, &amp;error);
01192     }
01193 
01194   <font class="keywordflow">if</font> (sitter)
01195     _dbus_babysitter_unref (sitter);
01196 
01197   <font class="keywordflow">if</font> (!dbus_error_is_set (&amp;error))
01198     {
01199       _dbus_warn (<font class="stringliteral">"Did not get an error launching nonexistent executable\n"</font>);
01200       <font class="keywordflow">return</font> FALSE;
01201     }
01202 
01203   <font class="keywordflow">if</font> (!(dbus_error_has_name (&amp;error, DBUS_ERROR_NO_MEMORY) ||
01204         dbus_error_has_name (&amp;error, DBUS_ERROR_SPAWN_EXEC_FAILED)))
01205     {
01206       _dbus_warn (<font class="stringliteral">"Not expecting error when launching nonexistent executable: %s: %s\n"</font>,
01207                   error.<a class="code" href="structDBusError.html#m0">name</a>, error.<a class="code" href="structDBusError.html#m1">message</a>);
01208       dbus_error_free (&amp;error);
01209       <font class="keywordflow">return</font> FALSE;
01210     }
01211 
01212   dbus_error_free (&amp;error);
01213   
01214   <font class="keywordflow">return</font> TRUE;
01215 }
01216 
01217 <font class="keyword">static</font> dbus_bool_t
01218 check_spawn_segfault (<font class="keywordtype">void</font> *data)
01219 {
01220   <font class="keywordtype">char</font> *argv[4] = { NULL, NULL, NULL, NULL };
01221   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter;
01222   <a class="code" href="structDBusError.html">DBusError</a> error;
01223   
01224   sitter = NULL;
01225   
01226   dbus_error_init (&amp;error);
01227 
01228   <font class="comment">/*** Test launching segfault binary */</font>
01229   
01230   argv[0] = TEST_SEGFAULT_BINARY;
01231   <font class="keywordflow">if</font> (_dbus_spawn_async_with_babysitter (&amp;sitter, argv,
01232                                          NULL, NULL,
01233                                          &amp;error))
01234     {
01235       _dbus_babysitter_block_for_child_exit (sitter);
01236       _dbus_babysitter_set_child_exit_error (sitter, &amp;error);
01237     }
01238 
01239   <font class="keywordflow">if</font> (sitter)
01240     _dbus_babysitter_unref (sitter);
01241 
01242   <font class="keywordflow">if</font> (!dbus_error_is_set (&amp;error))
01243     {
01244       _dbus_warn (<font class="stringliteral">"Did not get an error launching segfaulting binary\n"</font>);
01245       <font class="keywordflow">return</font> FALSE;
01246     }
01247 
01248   <font class="keywordflow">if</font> (!(dbus_error_has_name (&amp;error, DBUS_ERROR_NO_MEMORY) ||
01249         dbus_error_has_name (&amp;error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01250     {
01251       _dbus_warn (<font class="stringliteral">"Not expecting error when launching segfaulting executable: %s: %s\n"</font>,
01252                   error.<a class="code" href="structDBusError.html#m0">name</a>, error.<a class="code" href="structDBusError.html#m1">message</a>);
01253       dbus_error_free (&amp;error);
01254       <font class="keywordflow">return</font> FALSE;
01255     }
01256 
01257   dbus_error_free (&amp;error);
01258   
01259   <font class="keywordflow">return</font> TRUE;
01260 }
01261 
01262 <font class="keyword">static</font> dbus_bool_t
01263 check_spawn_exit (<font class="keywordtype">void</font> *data)
01264 {
01265   <font class="keywordtype">char</font> *argv[4] = { NULL, NULL, NULL, NULL };
01266   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter;
01267   <a class="code" href="structDBusError.html">DBusError</a> error;
01268   
01269   sitter = NULL;
01270   
01271   dbus_error_init (&amp;error);
01272 
01273   <font class="comment">/*** Test launching exit failure binary */</font>
01274   
01275   argv[0] = TEST_EXIT_BINARY;
01276   <font class="keywordflow">if</font> (_dbus_spawn_async_with_babysitter (&amp;sitter, argv,
01277                                          NULL, NULL,
01278                                          &amp;error))
01279     {
01280       _dbus_babysitter_block_for_child_exit (sitter);
01281       _dbus_babysitter_set_child_exit_error (sitter, &amp;error);
01282     }
01283 
01284   <font class="keywordflow">if</font> (sitter)
01285     _dbus_babysitter_unref (sitter);
01286 
01287   <font class="keywordflow">if</font> (!dbus_error_is_set (&amp;error))
01288     {
01289       _dbus_warn (<font class="stringliteral">"Did not get an error launching binary that exited with failure code\n"</font>);
01290       <font class="keywordflow">return</font> FALSE;
01291     }
01292 
01293   <font class="keywordflow">if</font> (!(dbus_error_has_name (&amp;error, DBUS_ERROR_NO_MEMORY) ||
01294         dbus_error_has_name (&amp;error, DBUS_ERROR_SPAWN_CHILD_EXITED)))
01295     {
01296       _dbus_warn (<font class="stringliteral">"Not expecting error when launching exiting executable: %s: %s\n"</font>,
01297                   error.<a class="code" href="structDBusError.html#m0">name</a>, error.<a class="code" href="structDBusError.html#m1">message</a>);
01298       dbus_error_free (&amp;error);
01299       <font class="keywordflow">return</font> FALSE;
01300     }
01301 
01302   dbus_error_free (&amp;error);
01303   
01304   <font class="keywordflow">return</font> TRUE;
01305 }
01306 
01307 <font class="keyword">static</font> dbus_bool_t
01308 check_spawn_and_kill (<font class="keywordtype">void</font> *data)
01309 {
01310   <font class="keywordtype">char</font> *argv[4] = { NULL, NULL, NULL, NULL };
01311   <a class="code" href="structDBusBabysitter.html">DBusBabysitter</a> *sitter;
01312   <a class="code" href="structDBusError.html">DBusError</a> error;
01313   
01314   sitter = NULL;
01315   
01316   dbus_error_init (&amp;error);
01317 
01318   <font class="comment">/*** Test launching sleeping binary then killing it */</font>
01319 
01320   argv[0] = TEST_SLEEP_FOREVER_BINARY;
01321   <font class="keywordflow">if</font> (_dbus_spawn_async_with_babysitter (&amp;sitter, argv,
01322                                          NULL, NULL,
01323                                          &amp;error))
01324     {
01325       _dbus_babysitter_kill_child (sitter);
01326       
01327       _dbus_babysitter_block_for_child_exit (sitter);
01328       
01329       _dbus_babysitter_set_child_exit_error (sitter, &amp;error);
01330     }
01331 
01332   <font class="keywordflow">if</font> (sitter)
01333     _dbus_babysitter_unref (sitter);
01334 
01335   <font class="keywordflow">if</font> (!dbus_error_is_set (&amp;error))
01336     {
01337       _dbus_warn (<font class="stringliteral">"Did not get an error after killing spawned binary\n"</font>);
01338       <font class="keywordflow">return</font> FALSE;
01339     }
01340 
01341   <font class="keywordflow">if</font> (!(dbus_error_has_name (&amp;error, DBUS_ERROR_NO_MEMORY) ||
01342         dbus_error_has_name (&amp;error, DBUS_ERROR_SPAWN_CHILD_SIGNALED)))
01343     {
01344       _dbus_warn (<font class="stringliteral">"Not expecting error when killing executable: %s: %s\n"</font>,
01345                   error.<a class="code" href="structDBusError.html#m0">name</a>, error.<a class="code" href="structDBusError.html#m1">message</a>);
01346       dbus_error_free (&amp;error);
01347       <font class="keywordflow">return</font> FALSE;
01348     }
01349 
01350   dbus_error_free (&amp;error);
01351   
01352   <font class="keywordflow">return</font> TRUE;
01353 }
01354 
01355 dbus_bool_t
01356 _dbus_spawn_test (<font class="keyword">const</font> <font class="keywordtype">char</font> *test_data_dir)
01357 {
01358   <font class="keywordflow">if</font> (!_dbus_test_oom_handling (<font class="stringliteral">"spawn_nonexistent"</font>,
01359                                 check_spawn_nonexistent,
01360                                 NULL))
01361     <font class="keywordflow">return</font> FALSE;
01362 
01363   <font class="keywordflow">if</font> (!_dbus_test_oom_handling (<font class="stringliteral">"spawn_segfault"</font>,
01364                                 check_spawn_segfault,
01365                                 NULL))
01366     <font class="keywordflow">return</font> FALSE;
01367 
01368   <font class="keywordflow">if</font> (!_dbus_test_oom_handling (<font class="stringliteral">"spawn_exit"</font>,
01369                                 check_spawn_exit,
01370                                 NULL))
01371     <font class="keywordflow">return</font> FALSE;
01372 
01373   <font class="keywordflow">if</font> (!_dbus_test_oom_handling (<font class="stringliteral">"spawn_and_kill"</font>,
01374                                 check_spawn_and_kill,
01375                                 NULL))
01376     <font class="keywordflow">return</font> FALSE;
01377   
01378   <font class="keywordflow">return</font> TRUE;
01379 }
01380 <font class="preprocessor">#endif</font>
</pre></div><hr><address align="right"><small>Generated on Wed Jun 9 05:01:26 2004 for D-BUS by
<a href="http://www.doxygen.org/index.html">
<img src="doxygen.png" alt="doxygen" align="middle" border=0 
width=110 height=53></a>1.2.15 </small></address>
</body>
</html>