Skip to content

fprintf is non-thread-safe #13194

Closed
@emaxx-google

Description

@emaxx-google

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions