Fix bug in redirection of unit test outputs
Avoid replacing handle. stdout is defined as a macro on several platforms.
Signed-off-by: gufe44 <gu981@protonmail.com>
diff --git a/ChangeLog.d/stdout-macro.txt b/ChangeLog.d/stdout-macro.txt
new file mode 100644
index 0000000..e77b0ad
--- /dev/null
+++ b/ChangeLog.d/stdout-macro.txt
@@ -0,0 +1,4 @@
+Bugfix
+ * Fix bug in redirection of unit test outputs on platforms where stdout is
+ defined as a macro. First reported in #2311 and fix contributed in #3528.
+ Adopted for LTS branch 2.16 in #3601.
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index cd9346e..8275733 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -391,45 +391,52 @@
#endif
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-static int redirect_output( FILE** out_stream, const char* path )
+static int redirect_output( FILE* out_stream, const char* path )
{
- int stdout_fd = dup( fileno( *out_stream ) );
+ int out_fd, dup_fd;
+ FILE* path_stream;
- if( stdout_fd == -1 )
+ out_fd = fileno( out_stream );
+ dup_fd = dup( out_fd );
+
+ if( dup_fd == -1 )
{
- return -1;
+ return( -1 );
}
- fflush( *out_stream );
- fclose( *out_stream );
- *out_stream = fopen( path, "w" );
-
- if( *out_stream == NULL )
+ path_stream = fopen( path, "w" );
+ if( path_stream == NULL )
{
- close( stdout_fd );
- return -1;
+ close( dup_fd );
+ return( -1 );
}
- return stdout_fd;
+ fflush( out_stream );
+ if( dup2( fileno( path_stream ), out_fd ) == -1 )
+ {
+ close( dup_fd );
+ fclose( path_stream );
+ return( -1 );
+ }
+
+ fclose( path_stream );
+ return( dup_fd );
}
-static int restore_output( FILE** out_stream, int old_fd )
+static int restore_output( FILE* out_stream, int dup_fd )
{
- fflush( *out_stream );
- fclose( *out_stream );
+ int out_fd = fileno( out_stream );
- *out_stream = fdopen( old_fd, "w" );
- if( *out_stream == NULL )
+ fflush( out_stream );
+ if( dup2( dup_fd, out_fd ) == -1 )
{
- return -1;
+ close( out_fd );
+ close( dup_fd );
+ return( -1 );
}
- return 0;
-}
-
-static void close_output( FILE* out_stream )
-{
- fclose( out_stream );
+ close( dup_fd );
+ return( 0 );
}
#endif /* __unix__ || __APPLE__ __MACH__ */
diff --git a/tests/suites/host_test.function b/tests/suites/host_test.function
index 4be6308..ca51e7b 100644
--- a/tests/suites/host_test.function
+++ b/tests/suites/host_test.function
@@ -555,7 +555,7 @@
*/
if( !option_verbose )
{
- stdout_fd = redirect_output( &stdout, "/dev/null" );
+ stdout_fd = redirect_output( stdout, "/dev/null" );
if( stdout_fd == -1 )
{
/* Redirection has failed with no stdout so exit */
@@ -575,7 +575,7 @@
}
#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
- if( !option_verbose && restore_output( &stdout, stdout_fd ) )
+ if( !option_verbose && restore_output( stdout, stdout_fd ) )
{
/* Redirection has failed with no stdout so exit */
exit( 1 );
@@ -667,10 +667,5 @@
mbedtls_memory_buffer_alloc_free();
#endif
-#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
- if( stdout_fd != -1 )
- close_output( stdout );
-#endif /* __unix__ || __APPLE__ __MACH__ */
-
return( total_errors != 0 );
}