title: Why does pclose return prematurely?
body: <p><strong>UPDATE 1: This question has been updated to eliminate the multithreading, simplifying its scope. The original problem <code>popen</code>ed in the main thread, and <code>pclose</code>d the child process in a different thread. The problem being asked about is reproducible much more simply, by doing the <code>popen</code> and <code>pclose</code> in the same (main) thread.</strong></p>
  <p><strong>Update 2: With help from responders at <a href="https://stackoverflow.com/questions/62732447/how-to-check-libc-version?noredirect=1#comment110938731_62732447">How to check libc version?</a>, I think I've identified that the libc being used is uClibc 0.9.30.</strong></p>
  <p>The following code <code>popen</code>s a script in the main thread, waits a little bit, then <code>pclose</code>s the child process in the same main thread. This program is cross-compiled for several cross-targets.</p>
  <p><em>The executable's code:</em></p>
  <pre><code>// mybin.c
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;stdarg.h&gt;
  #include &lt;stdbool.h&gt;
  #include &lt;string.h&gt;
  #include &lt;time.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;unistd.h&gt;
  
  static FILE* logFile = NULL;
  
  static void logInit( const char* fmt );
  static void log_( const char* file, int line, const char* fmt, ... );
  static void logCleanup();
  
  #define log(fmt, ...) log_( __FILE__, __LINE__, fmt, ##__VA_ARGS__ )
  
  int main( int argc, char* argv[] )
  {
    logInit( &quot;./mybin.log&quot; );
  
    {
      bool success = false;
      FILE* f;
  
      if ( ! (f = popen( &quot;./myscript&quot;, &quot;r&quot; )) )
      {
        log( &quot;popen error: %d (%s)&quot;, errno, strerror( errno ) );
        goto end;
      }
  
      log( &quot;before sleep&quot; );
      sleep( 1 );
      log( &quot;after sleep&quot; );
      pclose( f );
      log( &quot;after pclose&quot; );
  
      success = true;
    }
  
  end:
  
    log( &quot;At end&quot; );
    logCleanup();
  
    return 0;
  }
  
  /** Initializes logging */
  static void logInit( const char* file )
  {
    logFile = fopen( file, &quot;a&quot; );
  }
  
  /** Logs timestamp-prefixed, newline-suffixed printf-style text */
  static void log_( const char* file, int line, const char* fmt, ... )
  {
    //static FILE* logOut = logFile ? logFile : stdout;
    FILE* logOut = logFile ? logFile : stdout;
  
    time_t t = time( NULL );
    char fmtTime[16] = { '\0' };
    struct tm stm = *(localtime( &amp;t ));
    char logStr[1024] = { '\0' };
    va_list args;
  
    va_start( args, fmt );
    vsnprintf( logStr, sizeof logStr, fmt, args );
    va_end( args );
    strftime( fmtTime, sizeof fmtTime, &quot;%Y%m%d_%H%M%S&quot;, &amp;stm );
  
    fprintf( logOut, &quot;%s %s@%d %s\n&quot;, fmtTime, file, line, logStr );
  }
  
  /** Cleans up after logInit() */
  static void logCleanup()
  {
    if ( logFile ) { fclose( logFile ); }
  
    logFile = NULL;
  }
  </code></pre>
  <p><em>The script:</em></p>
  <pre><code>#! /bin/bash
  
  # mybin
  
  rm -f ./myscript.log
  for i in {1..10}; do echo &quot;$(date +&quot;%Y%m%d_%H%M%S&quot;) script is running&quot; &gt;&gt; ./myscript.log; sleep 1; done
  </code></pre>
  <p><strong>The expected behavior is that the compiled executable spawns execution of the script in a child process, waits for its completion, then exits. This is met on many cross-targets including x86, x64, and ARM.</strong> Below is an example architecture on which the expected behavior is met, compilation, and corresponding logs:</p>
  <pre><code>$ uname -a
  Linux linuxbox 5.4.8-200.fc31.x86_64 #1 SMP Mon Jan 6 16:44:18 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
  </code></pre>
  <p><em>Compilation:</em></p>
  <pre><code>$ gcc --version &amp;&amp; gcc -g ./mybin.c -lpthread -o mybin
  gcc (GCC) 9.2.1 20190827 (Red Hat 9.2.1-1)
  Copyright (C) 2019 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  
  $
  </code></pre>
  <p><em>mybin.log:</em></p>
  <pre><code>20200705_200950 ./mybin.c@33 before sleep
  20200705_200951 ./mybin.c@35 after sleep
  20200705_201000 ./mybin.c@37 after pclose
  20200705_201000 ./mybin.c@44 At end
  </code></pre>
  <p><em>myscript.log:</em></p>
  <pre><code>20200705_200950 script is running
  20200705_200951 script is running
  20200705_200952 script is running
  20200705_200953 script is running
  20200705_200954 script is running
  20200705_200955 script is running
  20200705_200956 script is running
  20200705_200957 script is running
  20200705_200958 script is running
  20200705_200959 script is running
  </code></pre>
  <p><strong>However, on <em>one</em> target, an odd thing occurs: <code>pclose</code> returns early: after the script has started running, but well before it has completed running -- why?</strong> Below is the problem architecture on which the <em>unexpected</em> behavior is observed, cross-compiler flags, and corresponding logs:</p>
  <pre><code>$ uname -a
  Linux hostname 2.6.33-arm1 #2 Wed Jul 1 23:05:25 UTC 2020 armv7ml GNU/Linux
  </code></pre>
  <p><em>Cross-compilation:</em></p>
  <pre><code>$ /path/to/toolchains/ARM-cortex-m3-4.4/bin/arm-uclinuxeabi-gcc --version
  arm-uclinuxeabi-gcc (Sourcery G++ Lite 2010q1-189) 4.4.1
  Copyright (C) 2009 Free Software Foundation, Inc.
  This is free software; see the source for copying conditions.  There is NO
  warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  
  $ /path/to/toolchains/ARM-cortex-m3-4.4/bin/arm-uclinuxeabi-gcc -O2 -Wall   -fno-strict-aliasing  -Os -D__uClinux__ -fno-strict-aliasing -mcpu=cortex-m3 -mthumb  -g -ffunction-sections -fdata-sections -I/path/to/toolchains/ARM-cortex-m3-4.4/usr/include/ -Wl,--gc-sections -Wl,-elf2flt=-s -Wl,-elf2flt=8192 -I/path/to/toolchains/ARM-cortex-m3-4.4/sysroot/usr/include -I/path/to/libs/ARM-cortex-m3-4.4/usr/include/ -L/path/to/toolchains/ARM-cortex-m3-4.4/sysroot/usr/lib  -lrt -L/path/to/libs/ARM-cortex-m3-4.4/usr/lib -L/path/to/libs/ARM-cortex-m3-4.4/lib -o mybin ./mybin.c  -lrt -lpthread
  $
  </code></pre>
  <p><em>mybin.log:</em></p>
  <pre><code>20200705_235632 ./mybin.c@33 before sleep
  20200705_235633 ./mybin.c@35 after sleep
  20200705_235633 ./mybin.c@37 after pclose
  20200705_235633 ./mybin.c@44 At end
  </code></pre>
  <p><em>myscript.log:</em></p>
  <pre><code>20200705_235632 script is running
  </code></pre>
  <p><strong>The gist of my question is: why does <code>pclose</code> return prematurely, and why only on this one cross-target?</strong></p>
  <p>Comments and research have me circling the notion that this is a bug in the variant/version of <code>libc</code> - it'd be great if someone knowledgeable on the subject could help confirm if that is the case.</p>
  <hr />
  <p>Not a dup of <a href="https://stackoverflow.com/questions/48159534/pclose-prematurely-returning-in-a-multi-threaded-environment-solaris-11">pclose() prematurely returning in a multi-threaded environment (Solaris 11)</a></p>