<br><div class="gmail_quote">On Wed, Apr 6, 2011 at 2:20 AM, Pierre GM <span dir="ltr"><<a href="mailto:pierregmcode@gmail.com">pierregmcode@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
All,<br>
<br>
I need to run a third-party binary from a python script and retrieve<br>
its output (and its error messages). I use something like<br>
>>> process = subprocess.Popen(options, stdout=subprocess.PIPE, stderr=subprocess.PIPE)<br>
>>> (info_out, info_err) = process.communicate()<br>
That works fine, except that the third-party binary in question<br>
doesn't behave very nicely and tend to segfaults without returning any<br>
error. In that case, `process.communicate` hangs for ever.<br>
<br>
I thought about calling a `threading.Timer` that would call<br>
`process.terminate` if `process.wait` doesn't return after a given<br>
time... But it's not really a solution: the process in question can<br>
sometimes take a long time to run, and I wouldn't want to kill a<br>
process still running.<br>
I also thought about polling every x s and stopping when the result of<br>
a subprocess.Popen(["ps","-p",str(initialprocess.pid)],<br>
stdout=subprocess.PIPE) becomes only the header line, but my script<br>
needs to run on Windows as well (and no ps over there)...<br>
<br>
Any suggestion welcome,<br>
Thx in advance<br>
P.<br>
<font color="#888888">--<br>
<a href="http://mail.python.org/mailman/listinfo/python-list" target="_blank">http://mail.python.org/mailman/listinfo/python-list</a><br>
</font></blockquote></div><br>I'm having a difficult time getting something to hang just from a segfault alone - my test code is below in shar format.  Are you pretty sure the process is segfaulting (usually verifiable with strace/truss/par/trace/etc)?  Based on what you've described, it sounds like there could be a buffering issue.<br>
<br>Note that Popen objects support poll() and wait() methods.  If you're truly not sending anything to the subprocess' stdin (I suppose your process could have had something redirected into it though), I doubt you'd need to worry about deadlocks much, so you probably could just read in a loop with select (where the select has a timeout) and a Popen.poll()<br>
<br>#!/bin/sh<br># This is a shell archive (produced by GNU sharutils 4.9).<br># To extract the files from this archive, save it to some FILE, remove<br># everything before the `#!/bin/sh' line above, then type `sh FILE'.<br>
#<br>lock_dir=_sh09253<br># Made on 2011-04-06 17:20 PDT by <dstromberg@benchbox>.<br># Source directory was `/home/dstromberg/segfault-subprocess'.<br>#<br># Existing files will *not* be overwritten, unless `-c' is specified.<br>
#<br># This shar contains:<br># length mode       name<br># ------ ---------- ------------------------------------------<br>#     64 -rw-r--r-- c.c<br>#     37 -rw-r--r-- Makefile<br>#    197 -rwxr-xr-x p<br>#<br>MD5SUM=${MD5SUM-md5sum}<br>
f=`${MD5SUM} --version | egrep '^md5sum .*(core|text)utils'`<br>test -n "${f}" && md5check=true || md5check=false<br>${md5check} || \<br>  echo 'Note: not verifying md5sums.  Consider installing GNU coreutils.'<br>
save_IFS="${IFS}"<br>IFS="${IFS}:"<br>gettext_dir=FAILED<br>locale_dir=FAILED<br>first_param="$1"<br>for dir in $PATH<br>do<br>  if test "$gettext_dir" = FAILED && test -f $dir/gettext \<br>
     && ($dir/gettext --version >/dev/null 2>&1)<br>  then<br>    case `$dir/gettext --version 2>&1 | sed 1q` in<br>      *GNU*) gettext_dir=$dir ;;<br>    esac<br>  fi<br>  if test "$locale_dir" = FAILED && test -f $dir/shar \<br>
     && ($dir/shar --print-text-domain-dir >/dev/null 2>&1)<br>  then<br>    locale_dir=`$dir/shar --print-text-domain-dir`<br>  fi<br>done<br>IFS="$save_IFS"<br>if test "$locale_dir" = FAILED || test "$gettext_dir" = FAILED<br>
then<br>  echo=echo<br>else<br>  TEXTDOMAINDIR=$locale_dir<br>  export TEXTDOMAINDIR<br>  TEXTDOMAIN=sharutils<br>  export TEXTDOMAIN<br>  echo="$gettext_dir/gettext -s"<br>fi<br>if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null<br>
then if (echo -n test; echo 1,2,3) | grep n >/dev/null<br>     then shar_n= shar_c='<br>'<br>     else shar_n=-n shar_c= ; fi<br>else shar_n= shar_c='\c' ; fi<br>f=shar-touch.$$<br>st1=200112312359.59<br>
st2=123123592001.59<br>st2tr=123123592001.5 # old SysV 14-char limit<br>st3=1231235901<br><br>if touch -am -t ${st1} ${f} >/dev/null 2>&1 && \<br>   test ! -f ${st1} && test -f ${f}; then<br>  shar_touch='touch -am -t $1$2$3$4$5$6.$7 "$8"'<br>
<br>elif touch -am ${st2} ${f} >/dev/null 2>&1 && \<br>   test ! -f ${st2} && test ! -f ${st2tr} && test -f ${f}; then<br>  shar_touch='touch -am $3$4$5$6$1$2.$7 "$8"'<br>
<br>elif touch -am ${st3} ${f} >/dev/null 2>&1 && \<br>   test ! -f ${st3} && test -f ${f}; then<br>  shar_touch='touch -am $3$4$5$6$2 "$8"'<br><br>else<br>  shar_touch=:<br>  echo<br>
  ${echo} 'WARNING: not restoring timestamps.  Consider getting and<br>installing GNU `touch'\'', distributed in GNU coreutils...'<br>  echo<br>fi<br>rm -f ${st1} ${st2} ${st2tr} ${st3} ${f}<br>#<br>if test ! -d ${lock_dir} ; then :<br>
else ${echo} "lock directory ${lock_dir} exists"<br>     exit 1<br>fi<br>if mkdir ${lock_dir}<br>then ${echo} "x - created lock directory ${lock_dir}."<br>else ${echo} "x - failed to create lock directory ${lock_dir}."<br>
     exit 1<br>fi<br># ============= c.c ==============<br>if test -f 'c.c' && test "$first_param" != -c; then<br>${echo} "x - SKIPPING c.c (file already exists)"<br>else<br>${echo} "x - extracting c.c (text)"<br>
  sed 's/^X//' << 'SHAR_EOF' > 'c.c' &&<br>X<br>#include <stdio.h><br>X<br>main()<br>X    {<br>X    char *p = NULL;<br>X    *p = '\0';<br>X    }<br>X<br>SHAR_EOF<br>  (set 20 11 04 06 17 12 05 'c.c'<br>
   eval "${shar_touch}") && \<br>  chmod 0644 'c.c'<br>if test $? -ne 0<br>then ${echo} "restore of c.c failed"<br>fi<br>  if ${md5check}<br>  then (<br>       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'c.c': 'MD5 check failed'<br>
       ) << \SHAR_EOF<br>bd21e6670ae7a9c711644290c45dc399  c.c<br>SHAR_EOF<br>  else<br>test `LC_ALL=C wc -c < 'c.c'` -ne 64 && \<br>  ${echo} "restoration warning:  size of 'c.c' is not 64"<br>
  fi<br>fi<br># ============= Makefile ==============<br>if test -f 'Makefile' && test "$first_param" != -c; then<br>${echo} "x - SKIPPING Makefile (file already exists)"<br>else<br>${echo} "x - extracting Makefile (text)"<br>
  sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&<br>X<br>go: c<br>X    ./p<br>X<br>c: c.c<br>X    $(CC) -o c c.c<br>X<br>SHAR_EOF<br>  (set 20 11 04 06 17 12 48 'Makefile'<br>   eval "${shar_touch}") && \<br>
  chmod 0644 'Makefile'<br>if test $? -ne 0<br>then ${echo} "restore of Makefile failed"<br>fi<br>  if ${md5check}<br>  then (<br>       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'Makefile': 'MD5 check failed'<br>
       ) << \SHAR_EOF<br>9d831f5d17a790719720363996179f44  Makefile<br>SHAR_EOF<br>  else<br>test `LC_ALL=C wc -c < 'Makefile'` -ne 37 && \<br>  ${echo} "restoration warning:  size of 'Makefile' is not 37"<br>
  fi<br>fi<br># ============= p ==============<br>if test -f 'p' && test "$first_param" != -c; then<br>${echo} "x - SKIPPING p (file already exists)"<br>else<br>${echo} "x - extracting p (text)"<br>
  sed 's/^X//' << 'SHAR_EOF' > 'p' &&<br>#!/usr/bin/python<br>X<br>import subprocess<br>X<br>process = subprocess.Popen('./c', stdout=subprocess.PIPE, stderr=subprocess.PIPE)<br>
(info_out, info_err) = process.communicate('foo')<br>print(process.returncode)<br>X<br>SHAR_EOF<br>  (set 20 11 04 06 17 19 15 'p'<br>   eval "${shar_touch}") && \<br>  chmod 0755 'p'<br>
if test $? -ne 0<br>then ${echo} "restore of p failed"<br>fi<br>  if ${md5check}<br>  then (<br>       ${MD5SUM} -c >/dev/null 2>&1 || ${echo} 'p': 'MD5 check failed'<br>       ) << \SHAR_EOF<br>
4484b44e31ea9c233139f76818aa2183  p<br>SHAR_EOF<br>  else<br>test `LC_ALL=C wc -c < 'p'` -ne 197 && \<br>  ${echo} "restoration warning:  size of 'p' is not 197"<br>  fi<br>fi<br>if rm -fr ${lock_dir}<br>
then ${echo} "x - removed lock directory ${lock_dir}."<br>else ${echo} "x - failed to remove lock directory ${lock_dir}."<br>     exit 1<br>fi<br>exit 0<br><br>