Skip to content

Commit 3192254

Browse files
committed
Handle failure of lseek in fflush
Unlike on linux (it seems) the emscripten lseek can fail for various reasons. For example, we do not support lseek on TTY or pipe file descriptors. Musl, it seems, just assumes that the seek succeeds and adjusts its internal buffers accordingly. The following (14) test expectation files were updated by running the tests with `--rebaseline`: ``` other/codesize/test_codesize_cxx_ctors1.size: 129141 => 129147 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_ctors2.size: 128553 => 128559 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_except.size: 170809 => 170815 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_except_wasm.size: 144517 => 144523 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_except_wasm_legacy.size: 142092 => 142098 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_lto.size: 122093 => 122099 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_mangle.size: 232619 => 232625 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_noexcept.size: 131704 => 131710 [+6 bytes / +0.00%] other/codesize/test_codesize_cxx_wasmfs.size: 169111 => 169117 [+6 bytes / +0.00%] other/codesize/test_codesize_files_wasmfs.size: 50049 => 50055 [+6 bytes / +0.01%] other/codesize/test_codesize_hello_O0.size: 15101 => 15105 [+4 bytes / +0.03%] other/codesize/test_codesize_minimal_O0.size: 1156 => 1160 [+4 bytes / +0.35%] other/test_unoptimized_code_size.wasm.size: 15101 => 15105 [+4 bytes / +0.03%] other/test_unoptimized_code_size_strict.wasm.size: 15101 => 15105 [+4 bytes / +0.03%] Average change: +0.03% (+0.00% - +0.35%) ```
1 parent b68ddc9 commit 3192254

20 files changed

+62
-23
lines changed

system/lib/libc/musl/src/stdio/fflush.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,22 @@ int fflush(FILE *f)
3434
}
3535

3636
/* If reading, sync position, per POSIX */
37+
#if __EMSCRIPTEN__
38+
/* Handle failues of lseek, which can happen in emscripten, e.g. for stdin etc */
39+
if (f->rpos != f->rend) {
40+
if (f->seek(f, f->rpos-f->rend, SEEK_CUR) == 0) {
41+
/* Clear read and write modes */
42+
f->wpos = f->wbase = f->wend = 0;
43+
f->rpos = f->rend = 0;
44+
}
45+
}
46+
#else
3747
if (f->rpos != f->rend) f->seek(f, f->rpos-f->rend, SEEK_CUR);
3848

3949
/* Clear read and write modes */
4050
f->wpos = f->wbase = f->wend = 0;
4151
f->rpos = f->rend = 0;
52+
#endif
4253

4354
FUNLOCK(f);
4455
return 0;

test/common.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,7 +1488,8 @@ def cleanup(line):
14881488

14891489
def run_js(self, filename, engine=None, args=None,
14901490
assert_returncode=0,
1491-
interleaved_output=True):
1491+
interleaved_output=True,
1492+
input=None):
14921493
# use files, as PIPE can get too full and hang us
14931494
stdout_file = self.in_dir('stdout')
14941495
stderr_file = None
@@ -1510,7 +1511,8 @@ def run_js(self, filename, engine=None, args=None,
15101511
jsrun.run_js(filename, engine, args,
15111512
stdout=stdout,
15121513
stderr=stderr,
1513-
assert_returncode=assert_returncode)
1514+
assert_returncode=assert_returncode,
1515+
input=input)
15141516
except subprocess.TimeoutExpired as e:
15151517
timeout_error = e
15161518
except subprocess.CalledProcessError as e:
@@ -1933,9 +1935,9 @@ def _build_and_run(self, filename, expected_output, args=None,
19331935
includes=None,
19341936
assert_returncode=0, assert_identical=False, assert_all=False,
19351937
check_for_error=True, force_c=False, emcc_args=None,
1936-
interleaved_output=True,
19371938
regex=False,
1938-
output_basename=None):
1939+
output_basename=None,
1940+
**kwargs):
19391941
logger.debug(f'_build_and_run: {filename}')
19401942

19411943
if no_build:
@@ -1959,9 +1961,7 @@ def _build_and_run(self, filename, expected_output, args=None,
19591961
if len(engines) == 0:
19601962
self.fail('No JS engine present to run this test with. Check %s and the paths therein.' % config.EM_CONFIG)
19611963
for engine in engines:
1962-
js_output = self.run_js(js_file, engine, args,
1963-
assert_returncode=assert_returncode,
1964-
interleaved_output=interleaved_output)
1964+
js_output = self.run_js(js_file, engine, args, assert_returncode=assert_returncode, **kwargs)
19651965
js_output = js_output.replace('\r\n', '\n')
19661966
if expected_output:
19671967
if type(expected_output) not in [list, tuple]:

test/jsrun.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ def require_engine(engine):
8686
def run_js(filename, engine, args=None,
8787
stdin=None, stdout=PIPE, stderr=None, cwd=None,
8888
full_output=False, assert_returncode=0, skip_check=False,
89-
timeout=DEFAULT_TIMEOUT):
89+
timeout=DEFAULT_TIMEOUT, **kwargs):
9090
"""Execute javascript code generated by tests, with possible timeout."""
9191

9292
# We used to support True here but we no longer do. Assert here just in case.
@@ -106,7 +106,8 @@ def run_js(filename, engine, args=None,
106106
stderr=stderr,
107107
cwd=cwd,
108108
timeout=timeout,
109-
universal_newlines=True)
109+
universal_newlines=True,
110+
**kwargs)
110111
except Exception:
111112
# the failure may be because the engine is not present. show the proper
112113
# error in that case
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
129141
1+
129147
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
128553
1+
128559
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
170809
1+
170815
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
144517
1+
144523
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
142092
1+
142098
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
122093
1+
122099
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
232619
1+
232625
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
131704
1+
131710
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
169111
1+
169117
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
50049
1+
50055
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
15101
1+
15105
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1156
1+
1160

test/other/test_stdin_fflush.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include <stdio.h>
2+
#include <string.h>
3+
4+
int main(int argc, char** argv) {
5+
char buf[10] = {0};
6+
7+
int cnt = 0;
8+
while (!feof(stdin)) {
9+
int cnt = fread(buf, 1, 3, stdin);
10+
printf("read %d bytes: '%s'\n", cnt, buf);
11+
fflush(stdin);
12+
memset(buf, 0, sizeof(buf));
13+
}
14+
15+
printf("done\n");
16+
return 0;
17+
}

test/other/test_stdin_fflush.out

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
read 3 bytes: 'foo'
2+
read 3 bytes: '
3+
ba'
4+
read 2 bytes: 'r
5+
'
6+
done
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
15101
1+
15105
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
15101
1+
15105

test/test_other.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1730,6 +1730,10 @@ def test_module_stdin(self):
17301730
self.emcc_args += ['--pre-js', 'pre.js']
17311731
self.do_runf('module/test_stdin.c', 'hello, world!')
17321732

1733+
@crossplatform
1734+
def test_stdin_fflush(self):
1735+
self.do_other_test('test_stdin_fflush.c', input='foo\nbar\n')
1736+
17331737
@crossplatform
17341738
def test_module_stdout_stderr(self):
17351739
self.set_setting('FORCE_FILESYSTEM')

0 commit comments

Comments
 (0)