Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fflush does not flush stdout or stderr in browser environment. #2770

Closed
juj opened this issue Sep 8, 2014 · 11 comments · Fixed by #2771
Closed

fflush does not flush stdout or stderr in browser environment. #2770

juj opened this issue Sep 8, 2014 · 11 comments · Fixed by #2771
Assignees
Labels

Comments

@juj
Copy link
Collaborator

juj commented Sep 8, 2014

Place the following code in the file test.cpp:

#include <stdio.h>

int main()
{
    printf("hello!");
    fflush(stdout);
    fprintf(stderr, "hello from stderr too!");
    fflush(stderr);
}

and compile with emcc test.cpp -o test.html -s NO_EXIT_RUNTIME=1. Then run the resulting test.html in the browser.

Observed: No text is printed.

Expected: fflush should flush, and both texts should be visible.

@juj
Copy link
Collaborator Author

juj commented Sep 8, 2014

Looking at the source, the cause is simply that fflush is currently not implemented: https://github.com/kripken/emscripten/blob/incoming/src/library.js#L2420

juj added a commit to juj/emscripten that referenced this issue Sep 8, 2014
juj added a commit to juj/emscripten that referenced this issue Sep 8, 2014
@juj juj mentioned this issue Sep 8, 2014
@juj juj self-assigned this Sep 8, 2014
@juj
Copy link
Collaborator Author

juj commented Sep 8, 2014

Implemented this in the above pull request. One limitation of our fflush is that it will always cause a newline to be printed.

@aknuds1
Copy link

aknuds1 commented Sep 15, 2014

Ran into the same issue, very confusing until I realized fflush wasn't working.

juj added a commit to juj/emscripten that referenced this issue Nov 18, 2014
juj added a commit to juj/emscripten that referenced this issue Nov 20, 2014
@juj
Copy link
Collaborator Author

juj commented Nov 24, 2014

Ouch, the situation is a bit trickier than I thought. I had to revert the fflush implementation for now, since it breaks printing to std::cerr completely. See this commit b759913

The main problem is that since printing to a web console is line-based, we cannot fflush without introducing a newline. std::cerr is unbuffered, and it flushes between every << operation, so implementing fflush to introduce a newline caused std::cerr to print its components each on their own lines, so that's not very good.

The old behavior where fflush was completely ignored is troublesome because there are often questions/bug reports coming in with "printf is not working", when the user forgets to add a newline \n to the end of the sequence that is printed, or they are explicitly calling fflush and are observing that it does not perform any function.

I'm not sure what's a good way to proceed here. One might be to attempt to remove the use of fflush in libc++, but it's a bit uncertain if that might affect some other uses, like syncing/flushing to file outputs, so not sure if we want to do that. Another might be to enable fflush only on a specific linking flag -s ENABLE_FFLUSH=1. That might at least give users who don't care about std::cerr something to work on. Perhaps a third way would be to always flush when 1) we exit main, and 2) when we exit a single iteration of the main loop. That still has the issue that fflush cannot be supported and must be a no-op.

If anyone has better suggestions, let me know.

@kripken
Copy link
Member

kripken commented Nov 24, 2014

I thought we already flush when we exit main? (I think when we shut down the FS) When I tested that now it worked using printf("text"); and nothing more.

Flushing on each main loop iteration is interesting. I'm sure it would help some things, but also break others. Not sure what is best.

@juj
Copy link
Collaborator Author

juj commented Nov 24, 2014

We flush when we exit main only when user did not call emscripten_set_main_loop and the user did not call -s NO_EXIT_RUNTIME=1, so practically, we don't flush when we exit main. I don't know what would be the best behavior here, it doesn't feel like we have a single way of "supporting everything" without breaking some other case.

@kripken
Copy link
Member

kripken commented Nov 24, 2014

I see, ok. Yes, we can't fix this 100%. I don't have any other ideas.

@ghost
Copy link

ghost commented Nov 24, 2014

We could do a "#define printf emscripten_internal_printf" in "emscripten.h" before the "stdio.h".

I think it could also work for the STL (cout ...).

In "emscripten_internal_printf()" we will know the state of the buffer. It is may be "fread/fwrite" to trap...

It is based on my understanding that the standart functions are replaced at link time.

May be I'm wrong...

dlmalloc do that for malloc().

@stale
Copy link

stale bot commented Aug 31, 2019

This issue has been automatically marked as stale because there has been no activity in the past 2 years. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.

@stale stale bot added the wontfix label Aug 31, 2019
@stale stale bot closed this as completed Sep 7, 2019
@xloem
Copy link
Contributor

xloem commented Mar 20, 2020

It looks to me like the solution to this would be to move the endline handling to the javascript side. So that '\n' is sent normal to javascript. Also note I've put some effort into implementing xterm at https://github.com/xloem/emterm which provides better for flushes of partial lines.

@vadimkantorov
Copy link

vadimkantorov commented Dec 21, 2020

@kripken Also hit the same issue while using busybox for an in-browser terminal application (https://busytex.github.io).

In particular, busybox clear doesn't print a new line: https://github.com/brgl/busybox/blob/master/console-tools/clear.c

This is aggravated by the fact that I don't let the emscripten module clean up and exit, and instead I reset the module's memory myself.

@sbc100 Is there a way to manually flush the streams from JavaScript side?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants