diff --git a/src/header/stdio/default.rs b/src/header/stdio/default.rs
index 90aa709b025c848085fdbe4110debd96f74bcfb4..341d76bd161e870467f89affe3dc5d739e68191e 100644
--- a/src/header/stdio/default.rs
+++ b/src/header/stdio/default.rs
@@ -2,13 +2,13 @@ use super::{constants, Buffer, BUFSIZ, FILE};
 use core::{cell::UnsafeCell, ptr};
 
 use crate::{fs::File, io::LineWriter, platform::types::*, sync::Mutex};
-use alloc::vec::Vec;
+use alloc::{boxed::Box, vec::Vec};
 
 pub struct GlobalFile(UnsafeCell<FILE>);
 impl GlobalFile {
     fn new(file: c_int, flags: c_int) -> Self {
         let file = File::new(file);
-        let writer = LineWriter::new(unsafe { file.get_ref() });
+        let writer = Box::new(LineWriter::new(unsafe { file.get_ref() }));
         GlobalFile(UnsafeCell::new(FILE {
             lock: Mutex::new(()),
 
diff --git a/src/header/stdio/ext.rs b/src/header/stdio/ext.rs
index 28bb73445af4556cb49f21e1d906fb6441c67b43..08aff1b2d2ee6498d953441542860e9b4b9f08b2 100644
--- a/src/header/stdio/ext.rs
+++ b/src/header/stdio/ext.rs
@@ -7,7 +7,7 @@ use crate::{
 pub extern "C" fn __fpending(stream: *mut FILE) -> size_t {
     let stream = unsafe { &mut *stream }.lock();
 
-    stream.writer.inner.buf.len() as size_t
+    stream.writer.pending()
 }
 
 #[no_mangle]
diff --git a/src/header/stdio/helpers.rs b/src/header/stdio/helpers.rs
index be7aa9fa0bb83cd3c203c8aca6d296e4d34ec384..dc42b100158a7002e1d475614bb0edf24adc580e 100644
--- a/src/header/stdio/helpers.rs
+++ b/src/header/stdio/helpers.rs
@@ -4,7 +4,7 @@ use super::{constants::*, Buffer, FILE};
 use crate::{
     fs::File,
     header::{errno, fcntl::*, string::strchr},
-    io::LineWriter,
+    io::BufWriter,
     platform::{self, types::*},
     sync::Mutex,
 };
@@ -62,7 +62,7 @@ pub unsafe fn _fdopen(fd: c_int, mode: *const c_char) -> Option<*mut FILE> {
     }
 
     let file = File::new(fd);
-    let writer = LineWriter::new(file.get_ref());
+    let writer = Box::new(BufWriter::new(file.get_ref()));
 
     Some(Box::into_raw(Box::new(FILE {
         lock: Mutex::new(()),
diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
index f6625766dda0df5928047a6149a75a949375d619..52bee2737ec5f926028e8ce4303e599cebe7285e 100644
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -24,7 +24,7 @@ use crate::{
         string::{self, strlen},
         unistd,
     },
-    io::{self, BufRead, LineWriter, Read, Write},
+    io::{self, BufRead, BufWriter, LineWriter, Read, Write},
     platform::{self, errno, types::*, Pal, Sys, WriteByte},
     sync::Mutex,
 };
@@ -69,6 +69,27 @@ impl<'a> DerefMut for Buffer<'a> {
     }
 }
 
+pub trait Pending {
+    fn pending(&self) -> size_t;
+}
+
+impl<W: core_io::Write> Pending for BufWriter<W> {
+    fn pending(&self) -> size_t {
+        self.buf.len() as size_t
+    }
+}
+
+impl<W: core_io::Write> Pending for LineWriter<W> {
+    fn pending(&self) -> size_t {
+        self.inner.buf.len() as size_t
+    }
+}
+
+pub trait Writer: Write + Pending {}
+
+impl<W: core_io::Write> Writer for BufWriter<W> {}
+impl<W: core_io::Write> Writer for LineWriter<W> {}
+
 /// This struct gets exposed to the C API.
 pub struct FILE {
     lock: Mutex<()>,
@@ -81,7 +102,7 @@ pub struct FILE {
     read_size: usize,
     unget: Vec<u8>,
     // pub for stdio_ext
-    pub(crate) writer: LineWriter<File>,
+    pub(crate) writer: Box<dyn Writer + Send>,
 
     // Optional pid for use with popen/pclose
     pid: Option<c_int>,
@@ -1145,3 +1166,12 @@ pub unsafe extern "C" fn vsscanf(s: *const c_char, format: *const c_char, ap: va
     let reader = (s as *const u8).into();
     scanf::scanf(reader, format, ap)
 }
+
+pub unsafe fn flush_io_streams() {
+    let flush = |stream: *mut FILE| {
+        let stream = &mut *stream;
+        stream.flush()
+    };
+    flush(stdout);
+    flush(stderr);
+}
diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index daaf72beaf2659ef38d3f3751ebfc74a205e5708..db708bcebce0bfd75b748ad42b875c7c261d9b01 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -16,6 +16,7 @@ use crate::{
         errno::{self, *},
         fcntl::*,
         limits,
+        stdio::flush_io_streams,
         string::*,
         time::constants::CLOCK_MONOTONIC,
         unistd::{self, sysconf, _SC_PAGESIZE},
@@ -297,6 +298,8 @@ pub unsafe extern "C" fn exit(status: c_int) {
 
     pthread_terminate();
 
+    flush_io_streams();
+
     Sys::exit(status);
 }
 
diff --git a/tests/expected/wchar/putwchar.stdout b/tests/expected/wchar/putwchar.stdout
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..42d65d1da021231040a6d7e35d1260aa89769751 100644
--- a/tests/expected/wchar/putwchar.stdout
+++ b/tests/expected/wchar/putwchar.stdout
@@ -0,0 +1 @@
+zß水🍌
\ No newline at end of file