Description
Emscripten's implementation of fprintf
isn't thread-safe in the sense that lines printed from different threads may interleave with each other, producing merged/corrupted messages in the result.
For example, when running the following program built under Emscripten:
#include <cstdio>
#include <string>
#include <thread>
void thread_main() {
std::string msg(100, 'a');
for (int i = 0; i < 10000; ++i)
fprintf(stderr, "%s\n", msg.c_str());
}
int main() {
std::thread t1(thread_main);
std::thread t2(thread_main);
t1.join();
t2.join();
}
with piping its result through sort -u
, it can be seen that besides the expected 100-character lines there are often 200-/300-character ones - obviously, the lines printed from different threads got collapsed and merged together.
This behavior doesn't seem to conform to the POSIX specification:
All functions that reference (FILE *) objects, except those with names ending in _unlocked, shall behave as if they use flockfile() and funlockfile() internally to obtain ownership of these (FILE *) objects.
(https://pubs.opengroup.org/onlinepubs/9699919799/functions/flockfile.html)
The same program compiled using the normal g++
with the standard libc always produces only the expected 100-line characters on my Linux machine.