[libc-commits] [libc] [libc][Fix]: flush stdout on normal exit (PR #227143)

David Dada via libc-commits libc-commits at lists.llvm.org
Wed Oct 7 03:13:08 PDT 2026


https://github.com/obadafidii updated https://github.com/llvm/llvm-project/pull/227143

>From d029df6621a4ae65a178d9833e6159f8daa2d6f1 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Mon, 21 Sep 2026 21:12:43 +0100
Subject: [PATCH 1/6] mark where I need start from after several studies

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdlib/exit.cpp       | 1 +
 libc/src/stdlib/exit_handler.h | 7 +++++++
 libc/src/stdlib/quick_exit.cpp | 1 +
 3 files changed, 9 insertions(+)

diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp
index ab43a52b04b9fa..6810aa929e8f77 100644
--- a/libc/src/stdlib/exit.cpp
+++ b/libc/src/stdlib/exit.cpp
@@ -26,6 +26,7 @@ extern "C" void __cxa_finalize(void *);
   internal::call_atexit_callbacks();
 #endif
   __cxa_finalize(nullptr);
+  // TODO: flushing needs to happen here
   internal::exit(status);
 }
 
diff --git a/libc/src/stdlib/exit_handler.h b/libc/src/stdlib/exit_handler.h
index e9d163dfe90244..d7aa551f476005 100644
--- a/libc/src/stdlib/exit_handler.h
+++ b/libc/src/stdlib/exit_handler.h
@@ -45,6 +45,13 @@ LIBC_INLINE void stdc_at_exit_func(void *payload) {
   reinterpret_cast<StdCAtExitCallback *>(payload)();
 }
 
+// so this is the guy executing all callbacks before the exit is completed
+// and I need to make sure
+//
+// Resourcesful link:
+// https://stackoverflow.com/questions/50370985/difference-atexit-and-at-quick-exit
+// https://en.cppreference.com/cpp/utility/program/at_quick_exit
+// https://en.cppreference.com/cpp/utility/program/atexit
 LIBC_INLINE void call_exit_callbacks(ExitCallbackList &callbacks) {
   handler_list_mtx.lock();
   while (!callbacks.empty()) {
diff --git a/libc/src/stdlib/quick_exit.cpp b/libc/src/stdlib/quick_exit.cpp
index a5abf3e05d1a13..0dd382d03829df 100644
--- a/libc/src/stdlib/quick_exit.cpp
+++ b/libc/src/stdlib/quick_exit.cpp
@@ -19,6 +19,7 @@ extern ExitCallbackList at_quick_exit_callbacks;
 
 [[noreturn]] LLVM_LIBC_FUNCTION(void, quick_exit, (int status)) {
   call_exit_callbacks(at_quick_exit_callbacks);
+  // TODO: flushing should happen here
   internal::exit(status);
 }
 

>From 42f7840948b6bff77406d30f8a0dd19f2f671ace Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Mon, 28 Sep 2026 14:31:09 +0100
Subject: [PATCH 2/6] feat: add additional namespaces for baremetal, gpu and
 generic to distinguish each implementation

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/baremetal/fflush.cpp | 3 ++-
 libc/src/stdio/generic/fflush.cpp   | 5 ++++-
 libc/src/stdio/gpu/fflush.cpp       | 8 +++++++-
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/libc/src/stdio/baremetal/fflush.cpp b/libc/src/stdio/baremetal/fflush.cpp
index 4a39c25ae11c9b..97591250319d44 100644
--- a/libc/src/stdio/baremetal/fflush.cpp
+++ b/libc/src/stdio/baremetal/fflush.cpp
@@ -11,12 +11,13 @@
 #include "src/__support/common.h"
 
 namespace LIBC_NAMESPACE_DECL {
-
+namespace FflushBaremetal {
 // Baremetal uses unbuffered I/O, so there is nothing to flush.
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   (void)stream;
   // TODO: Shall we have an embedding API for fflush?
   return 0;
 }
+} // namespace FflushBaremetal
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/generic/fflush.cpp b/libc/src/stdio/generic/fflush.cpp
index 87888770937bff..7d56488ccc950d 100644
--- a/libc/src/stdio/generic/fflush.cpp
+++ b/libc/src/stdio/generic/fflush.cpp
@@ -18,6 +18,9 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
+namespace FflushGeneric {
+// NOTES: This is the generic implementation of fflush
+//  not considering cpu, gpu or baremetal development
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   // If a non-null stream is specified, we only flush that single stream.
   if (stream != nullptr) {
@@ -62,5 +65,5 @@ LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   }
   return 0;
 }
-
+} // namespace FflushGeneric
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/gpu/fflush.cpp b/libc/src/stdio/gpu/fflush.cpp
index 3032554cd11c01..11d7d5904f0bcf 100644
--- a/libc/src/stdio/gpu/fflush.cpp
+++ b/libc/src/stdio/gpu/fflush.cpp
@@ -13,7 +13,12 @@
 #include "src/__support/common.h"
 
 namespace LIBC_NAMESPACE_DECL {
-
+// create a new namespace for gpu to differentiate which fflush
+// implementation we are using.
+//
+// TODO: don't forget to test, but how will I tests for GPU
+// TODO: Check it out.
+namespace FflushGPU {
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   int ret;
   rpc::Client::Port port = rpc::client.open<LIBC_FFLUSH>();
@@ -26,5 +31,6 @@ LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
       });
   return ret;
 }
+} // namespace FflushGPU
 
 } // namespace LIBC_NAMESPACE_DECL

>From 2d99920951be3924f5a0dfdde6eb141e71716a9e Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Mon, 28 Sep 2026 14:32:18 +0100
Subject: [PATCH 3/6] feat(fflush): add a combiner function resolving the
 specific implementations of fflush based on the cmake build args

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/fflush.cpp | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 libc/src/stdio/fflush.cpp

diff --git a/libc/src/stdio/fflush.cpp b/libc/src/stdio/fflush.cpp
new file mode 100644
index 00000000000000..265bdf679cc5ec
--- /dev/null
+++ b/libc/src/stdio/fflush.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file handles the resolution of the specific fflush function based on
+/// the build type
+///
+//===----------------------------------------------------------------------===//
+
+#if defined(LIBC_TARGET_ARCH_IS_GPU)
+#include "./gpu/fflush.cpp"
+#elif defined(LIBC_TARGET_OS_IS_BAREMETAL)
+#include "./baremetal/fflush.cpp"
+#else
+#include "./generic/fflush.cpp"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+
+// fflush handles the resolution of function call
+// based on CMAKE build args, allowing the callers
+// of fflush to be bothered about different implementations
+// for different architectures (cpu, gpu or baremetal)
+int fflush(::FILE *stream) {
+#if defined(LIBC_TARGET_ARCH_IS_GPU)
+  return ::FflushGPU::fflush(stream);
+#elif defined(LIBC_TARGET_OS_IS_BAREMETAL)
+  return ::FflushBaremetal::fflush(stream);
+#else
+  return ::FflushGeneric::fflush(stream);
+#endif
+}
+} // namespace LIBC_NAMESPACE_DECL

>From ce7ac55f52d6b8ef8f8958fe4364f0bf86b10920 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Mon, 28 Sep 2026 21:27:04 +0100
Subject: [PATCH 4/6] feat: add namespaces to differentiate implementations

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/baremetal/fflush.cpp |  5 ++--
 libc/src/stdio/fflush.cpp           | 38 -----------------------------
 libc/src/stdio/generic/fflush.cpp   |  5 ++--
 libc/src/stdio/gpu/fflush.cpp       |  4 +--
 libc/src/stdlib/CMakeLists.txt      |  2 +-
 libc/src/stdlib/exit.cpp            |  5 +++-
 6 files changed, 12 insertions(+), 47 deletions(-)
 delete mode 100644 libc/src/stdio/fflush.cpp

diff --git a/libc/src/stdio/baremetal/fflush.cpp b/libc/src/stdio/baremetal/fflush.cpp
index 97591250319d44..91bdbe71c4c2b8 100644
--- a/libc/src/stdio/baremetal/fflush.cpp
+++ b/libc/src/stdio/baremetal/fflush.cpp
@@ -11,13 +11,12 @@
 #include "src/__support/common.h"
 
 namespace LIBC_NAMESPACE_DECL {
-namespace FflushBaremetal {
+namespace BAREMETAL_FFLUSH {
 // Baremetal uses unbuffered I/O, so there is nothing to flush.
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   (void)stream;
   // TODO: Shall we have an embedding API for fflush?
   return 0;
 }
-} // namespace FflushBaremetal
-
+}
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/fflush.cpp b/libc/src/stdio/fflush.cpp
deleted file mode 100644
index 265bdf679cc5ec..00000000000000
--- a/libc/src/stdio/fflush.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// This file handles the resolution of the specific fflush function based on
-/// the build type
-///
-//===----------------------------------------------------------------------===//
-
-#if defined(LIBC_TARGET_ARCH_IS_GPU)
-#include "./gpu/fflush.cpp"
-#elif defined(LIBC_TARGET_OS_IS_BAREMETAL)
-#include "./baremetal/fflush.cpp"
-#else
-#include "./generic/fflush.cpp"
-#endif
-
-namespace LIBC_NAMESPACE_DECL {
-
-// fflush handles the resolution of function call
-// based on CMAKE build args, allowing the callers
-// of fflush to be bothered about different implementations
-// for different architectures (cpu, gpu or baremetal)
-int fflush(::FILE *stream) {
-#if defined(LIBC_TARGET_ARCH_IS_GPU)
-  return ::FflushGPU::fflush(stream);
-#elif defined(LIBC_TARGET_OS_IS_BAREMETAL)
-  return ::FflushBaremetal::fflush(stream);
-#else
-  return ::FflushGeneric::fflush(stream);
-#endif
-}
-} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/generic/fflush.cpp b/libc/src/stdio/generic/fflush.cpp
index 7d56488ccc950d..778e4cc8418cc0 100644
--- a/libc/src/stdio/generic/fflush.cpp
+++ b/libc/src/stdio/generic/fflush.cpp
@@ -18,7 +18,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-namespace FflushGeneric {
+namespace GENERIC_FLUSH {
 // NOTES: This is the generic implementation of fflush
 //  not considering cpu, gpu or baremetal development
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
@@ -65,5 +65,6 @@ LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   }
   return 0;
 }
-} // namespace FflushGeneric
+} // namespace GENERIC_FLUSH
+
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/gpu/fflush.cpp b/libc/src/stdio/gpu/fflush.cpp
index 11d7d5904f0bcf..289e1cfadf14c8 100644
--- a/libc/src/stdio/gpu/fflush.cpp
+++ b/libc/src/stdio/gpu/fflush.cpp
@@ -13,12 +13,12 @@
 #include "src/__support/common.h"
 
 namespace LIBC_NAMESPACE_DECL {
+namespace GPU_FLUSH {
 // create a new namespace for gpu to differentiate which fflush
 // implementation we are using.
 //
 // TODO: don't forget to test, but how will I tests for GPU
 // TODO: Check it out.
-namespace FflushGPU {
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   int ret;
   rpc::Client::Port port = rpc::client.open<LIBC_FFLUSH>();
@@ -31,6 +31,6 @@ LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
       });
   return ret;
 }
-} // namespace FflushGPU
+}
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index faa31c62d1d8e8..a54c4058ce6718 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -846,6 +846,7 @@ add_entrypoint_object(
     ${exit_compile_options}
   DEPENDS
     ${exit_deps}
+    libc.src.stdio.fflush
 )
 
 add_header_library(
@@ -872,4 +873,3 @@ add_entrypoint_object(
   DEPENDS
     .${LIBC_TARGET_OS}.system
 )
-
diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp
index 6810aa929e8f77..7f43077d617a7b 100644
--- a/libc/src/stdlib/exit.cpp
+++ b/libc/src/stdlib/exit.cpp
@@ -10,6 +10,9 @@
 #include "src/__support/OSUtil/exit.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
+#include "src/stdio/fflush.h"
+
+#include <src/string/memory_utils/op_generic.h>
 
 #ifdef LIBC_COPT_SUPPORT_THREADS
 #include "src/__support/threads/thread.h"
@@ -26,7 +29,7 @@ extern "C" void __cxa_finalize(void *);
   internal::call_atexit_callbacks();
 #endif
   __cxa_finalize(nullptr);
-  // TODO: flushing needs to happen here
+  LIBC_NAMESPACE::fflush(nullptr);
   internal::exit(status);
 }
 

>From 4d2037b44e2ebc257e9587a0fa3cba6af4016354 Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Tue, 6 Oct 2026 19:22:43 +0100
Subject: [PATCH 5/6] fix add dependencies needed for compiling and executing
 tests

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/CMakeLists.txt  | 22 +++++++++++++++++++++-
 libc/src/stdlib/CMakeLists.txt |  2 +-
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/libc/src/stdio/CMakeLists.txt b/libc/src/stdio/CMakeLists.txt
index d475ad5d7708cf..5000cb19d2eebd 100644
--- a/libc/src/stdio/CMakeLists.txt
+++ b/libc/src/stdio/CMakeLists.txt
@@ -28,6 +28,26 @@ if(NOT LLVM_LIBC_FULL_BUILD)
   libc_add_definition(use_system_file "LIBC_COPT_STDIO_USE_SYSTEM_FILE")
 endif()
 
+add_entrypoint_object(
+  fflush
+  SRCS
+    fflush.cpp
+  HDRS
+    fflush.h
+    stdin.h
+    stdout.h
+    stderr.h
+  DEPENDS
+    libc.src.errno.errno
+    libc.hdr.types.FILE
+    libc.src.__support.File.file
+    libc.src.__support.File.platform_file
+    libc.src.stdio.stdin
+    libc.src.stdio.stdout
+    libc.src.stdio.stderr
+)
+
+
 add_entrypoint_object(
   flockfile
   SRCS
@@ -303,7 +323,7 @@ add_stdio_entrypoint_object(ftell)
 add_stdio_entrypoint_object(fseeko)
 add_stdio_entrypoint_object(fileno)
 add_stdio_entrypoint_object(ftello)
-add_stdio_entrypoint_object(fflush)
+# add_stdio_entrypoint_object(fflush)
 add_stdio_entrypoint_object(clearerr)
 add_stdio_entrypoint_object(clearerr_unlocked)
 add_stdio_entrypoint_object(fopen)
diff --git a/libc/src/stdlib/CMakeLists.txt b/libc/src/stdlib/CMakeLists.txt
index a54c4058ce6718..8548f311e62499 100644
--- a/libc/src/stdlib/CMakeLists.txt
+++ b/libc/src/stdlib/CMakeLists.txt
@@ -845,8 +845,8 @@ add_entrypoint_object(
   COMPILE_OPTIONS
     ${exit_compile_options}
   DEPENDS
-    ${exit_deps}
     libc.src.stdio.fflush
+    ${exit_deps}
 )
 
 add_header_library(

>From 90b9c0a81499074129deebedcaffbc5211fe5a7d Mon Sep 17 00:00:00 2001
From: tdadadavid <davidtofunmidada at gmail.com>
Date: Wed, 7 Oct 2026 08:36:33 +0100
Subject: [PATCH 6/6] implement abstraction for fflush

Signed-off-by: tdadadavid <davidtofunmidada at gmail.com>
---
 libc/src/stdio/fflush.cpp         | 38 +++++++++++++++++++++++++++++++
 libc/src/stdio/generic/fflush.cpp |  4 ++--
 libc/src/stdio/gpu/fflush.cpp     |  4 ++--
 libc/src/stdlib/exit.cpp          |  2 --
 libc/src/stdlib/exit_handler.h    |  2 ++
 5 files changed, 44 insertions(+), 6 deletions(-)
 create mode 100644 libc/src/stdio/fflush.cpp

diff --git a/libc/src/stdio/fflush.cpp b/libc/src/stdio/fflush.cpp
new file mode 100644
index 00000000000000..d43b6d022683b3
--- /dev/null
+++ b/libc/src/stdio/fflush.cpp
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file contains the fflush function which returns the specific
+/// implementation based on CMake flags.
+///
+//===----------------------------------------------------------------------===//
+
+#include "src/stdio/fflush.h"
+#include "hdr/types/FILE.h"
+
+#if defined(LIBC_TARGET_ARCH_IS_GPU)
+#include "src/stdio/gpu/fflush.cpp"
+#elif defined(LIBC_TARGET_OS_IS_BAREMETAL)
+#include "src/stdio/baremetal/fflush.cpp"
+#else
+#include "src/stdio/generic/fflush.cpp"
+#endif
+
+namespace LIBC_NAMESPACE_DECL {
+
+int fflush(::FILE *stream) {
+#if defined(LIBC_TARGET_ARCH_IS_GPU)
+  return GPU_FFLUSH::fflush(stream);
+#elif defined(LIBC_TARGET_OS_IS_BAREMETAL)
+  return BAREMETAL_FFLUSH::fflush(stream);
+#else
+  return GENERIC_FFLUSH::fflush(stream);
+#endif
+}
+
+} // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/generic/fflush.cpp b/libc/src/stdio/generic/fflush.cpp
index 778e4cc8418cc0..1e4b52dfdfc90d 100644
--- a/libc/src/stdio/generic/fflush.cpp
+++ b/libc/src/stdio/generic/fflush.cpp
@@ -18,7 +18,7 @@
 
 namespace LIBC_NAMESPACE_DECL {
 
-namespace GENERIC_FLUSH {
+namespace GENERIC_FFLUSH {
 // NOTES: This is the generic implementation of fflush
 //  not considering cpu, gpu or baremetal development
 LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
@@ -65,6 +65,6 @@ LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
   }
   return 0;
 }
-} // namespace GENERIC_FLUSH
+} // namespace GENERIC_FFLUSH
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdio/gpu/fflush.cpp b/libc/src/stdio/gpu/fflush.cpp
index 289e1cfadf14c8..ae01aa256b3b61 100644
--- a/libc/src/stdio/gpu/fflush.cpp
+++ b/libc/src/stdio/gpu/fflush.cpp
@@ -13,7 +13,7 @@
 #include "src/__support/common.h"
 
 namespace LIBC_NAMESPACE_DECL {
-namespace GPU_FLUSH {
+namespace GPU_FFLUSH {
 // create a new namespace for gpu to differentiate which fflush
 // implementation we are using.
 //
@@ -31,6 +31,6 @@ LLVM_LIBC_FUNCTION(int, fflush, (::FILE * stream)) {
       });
   return ret;
 }
-}
+} // namespace GPU_FFLUSH
 
 } // namespace LIBC_NAMESPACE_DECL
diff --git a/libc/src/stdlib/exit.cpp b/libc/src/stdlib/exit.cpp
index 7f43077d617a7b..db4fb87c227f9d 100644
--- a/libc/src/stdlib/exit.cpp
+++ b/libc/src/stdlib/exit.cpp
@@ -12,8 +12,6 @@
 #include "src/__support/macros/config.h"
 #include "src/stdio/fflush.h"
 
-#include <src/string/memory_utils/op_generic.h>
-
 #ifdef LIBC_COPT_SUPPORT_THREADS
 #include "src/__support/threads/thread.h"
 #endif
diff --git a/libc/src/stdlib/exit_handler.h b/libc/src/stdlib/exit_handler.h
index d7aa551f476005..a00e332811b152 100644
--- a/libc/src/stdlib/exit_handler.h
+++ b/libc/src/stdlib/exit_handler.h
@@ -15,6 +15,7 @@
 #include "src/__support/fixedvector.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/threads/mutex.h"
+#include "src/stdio/fflush.h"
 
 namespace LIBC_NAMESPACE_DECL {
 
@@ -62,6 +63,7 @@ LIBC_INLINE void call_exit_callbacks(ExitCallbackList &callbacks) {
     handler_list_mtx.lock();
   }
   ExitCallbackList::destroy(&callbacks);
+  LIBC_NAMESPACE::fflush(nullptr);
 }
 
 LIBC_INLINE int add_atexit_unit(ExitCallbackList &callbacks,



More information about the libc-commits mailing list