Skip to content

fprintf is non-thread-safe #13194

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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