diff --git a/std/stdio.d b/std/stdio.d index 0c315026..8b1860d0 100644 --- a/std/stdio.d +++ b/runtime/phobos/std/stdio.d @@ -310,6 +310,45 @@ else version (GENERIC_IO) void funlockfile(FILE*); } + version(CRuntime_Bionic) + { + import core.stdc.wchar_ : mbstate_t; + import core.sys.posix.sys.types : pthread_mutex_t; + + extern(C) struct wchar_io_data + { + mbstate_t wcio_mbstate_in; + mbstate_t wcio_mbstate_out; + wchar_t[1] wcio_ungetwc_buf; + size_t wcio_ungetwc_inbuf; + int wcio_mode; + } + + extern(C) struct __sfileext + { + __sbuf _ub; + wchar_io_data _wcio; + pthread_mutex_t _lock; + } + + void bionic_lock(FILE* foo) + { + if( foo == stdout._p.handle || foo == stdin._p.handle || foo == stderr._p.handle) + { + auto ext = cast(__sfileext*) foo._ext._base; + if (ext._lock.value == 0) + { + // A bionic regression in Android 5.0 leaves + // the mutex for stdout/err/in uninitialized, + // so check for that and initialize it. + printf("lock is zero, initializing...\n"); + ext._lock.value = 0x4000; + } + } + flockfile(foo); + } + } + int fputc_unlocked(int c, _iobuf* fp) { return fputc(c, cast(shared) fp); } int fputwc_unlocked(wchar_t c, _iobuf* fp) { @@ -328,7 +367,10 @@ else version (GENERIC_IO) alias FGETC = fgetc_unlocked; alias FGETWC = fgetwc_unlocked; - alias FLOCK = flockfile; + version(CRuntime_Bionic) + alias FLOCK = bionic_lock; + else + alias FLOCK = flockfile; alias FUNLOCK = funlockfile; } else