Skip to content

Commit cfacd7d

Browse files
socketpairjakogut
authored andcommitted
Fix dup*() syscalls, close emscripten-core#4017
1 parent 44593ac commit cfacd7d

File tree

3 files changed

+58
-16
lines changed

3 files changed

+58
-16
lines changed

src/library_syscall.js

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,12 @@ var SyscallsLibrary = {
128128
}
129129
return 0;
130130
},
131-
doDup: function(path, flags, suggestFD) {
131+
doDup: function(stream, suggestFD) {
132132
var suggest = FS.getStream(suggestFD);
133133
if (suggest) FS.close(suggest);
134-
return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
134+
135+
FS.streams[suggestFD] = stream;
136+
return suggestFD;
135137
},
136138
doReadv: function(stream, iov, iovcnt, offset) {
137139
var ret = 0;
@@ -375,7 +377,7 @@ var SyscallsLibrary = {
375377
},
376378
__syscall41: function(which, varargs) { // dup
377379
var old = SYSCALLS.getStreamFromFD();
378-
return FS.open(old.path, old.flags, 0).fd;
380+
return SYSCALLS.doDup(old, FS.nextfd());
379381
},
380382
__syscall42__deps: ['$PIPEFS'],
381383
__syscall42: function(which, varargs) { // pipe
@@ -468,7 +470,7 @@ var SyscallsLibrary = {
468470
__syscall63: function(which, varargs) { // dup2
469471
var old = SYSCALLS.getStreamFromFD(), suggestFD = SYSCALLS.get();
470472
if (old.fd === suggestFD) return suggestFD;
471-
return SYSCALLS.doDup(old.path, old.flags, suggestFD);
473+
return SYSCALLS.doDup(old, suggestFD);
472474
},
473475
__syscall64__deps: ['$PROCINFO'],
474476
__syscall64: function(which, varargs) { // getppid
@@ -666,7 +668,7 @@ var SyscallsLibrary = {
666668
for (var i = 0; i < num; i++) {
667669
var iovbase = {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_base, 'i8*') }}};
668670
var iovlen = {{{ makeGetValue('iov', '(' + C_STRUCTS.iovec.__size__ + ' * i) + ' + C_STRUCTS.iovec.iov_len, 'i32') }}};
669-
for (var j = 0; j < iovlen; j++) {
671+
for (var j = 0; j < iovlen; j++) {
670672
view[offset++] = {{{ makeGetValue('iovbase', 'j', 'i8') }}};
671673
}
672674
}
@@ -852,7 +854,7 @@ var SyscallsLibrary = {
852854
#endif
853855

854856
var total = 0;
855-
857+
856858
var srcReadLow = (readfds ? {{{ makeGetValue('readfds', 0, 'i32') }}} : 0),
857859
srcReadHigh = (readfds ? {{{ makeGetValue('readfds', 4, 'i32') }}} : 0);
858860
var srcWriteLow = (writefds ? {{{ makeGetValue('writefds', 0, 'i32') }}} : 0),
@@ -919,7 +921,7 @@ var SyscallsLibrary = {
919921
{{{ makeSetValue('exceptfds', '0', 'dstExceptLow', 'i32') }}};
920922
{{{ makeSetValue('exceptfds', '4', 'dstExceptHigh', 'i32') }}};
921923
}
922-
924+
923925
return total;
924926
},
925927
__syscall144: function(which, varargs) { // msync
@@ -1184,14 +1186,14 @@ var SyscallsLibrary = {
11841186
#else
11851187
var stream = SYSCALLS.getStreamFromFD(), cmd = SYSCALLS.get();
11861188
switch (cmd) {
1189+
// TODO: FreeBSD also defines F_DUP2FD and F_DUP2FD_CLOEXEC
1190+
case {{{ cDefine('F_DUPFD_CLOEXEC') }}}: // ignore O_CLOEXEC in single process environment
11871191
case {{{ cDefine('F_DUPFD') }}}: {
11881192
var arg = SYSCALLS.get();
11891193
if (arg < 0) {
11901194
return -{{{ cDefine('EINVAL') }}};
11911195
}
1192-
var newStream;
1193-
newStream = FS.open(stream.path, stream.flags, 0, arg);
1194-
return newStream.fd;
1196+
return SYSCALLS.doDup(stream, FS.nextfd(arg));
11951197
}
11961198
case {{{ cDefine('F_GETFD') }}}:
11971199
case {{{ cDefine('F_SETFD') }}}:
@@ -1400,7 +1402,7 @@ var SyscallsLibrary = {
14001402
nanoseconds = {{{ makeGetValue('times', C_STRUCTS.timespec.tv_nsec, 'i32') }}};
14011403
var mtime = (seconds*1000) + (nanoseconds/(1000*1000));
14021404
FS.utime(path, atime, mtime);
1403-
return 0;
1405+
return 0;
14041406
},
14051407
__syscall324: function(which, varargs) { // fallocate
14061408
var stream = SYSCALLS.getStreamFromFD(), mode = SYSCALLS.get(), offset = SYSCALLS.get64(), len = SYSCALLS.get64();
@@ -1418,8 +1420,13 @@ var SyscallsLibrary = {
14181420
#if ASSERTIONS
14191421
assert(!flags);
14201422
#endif
1421-
if (old.fd === suggestFD) return -{{{ cDefine('EINVAL') }}};
1422-
return SYSCALLS.doDup(old.path, old.flags, suggestFD);
1423+
if (old.fd === suggestFD) return -ERRNO_CODES.EINVAL;
1424+
1425+
// intentionally ignore flags, since O_CLOEXEC make no sense in
1426+
// singleprocess environment
1427+
if (flags & ~{{{ cDefine('O_CLOEXEC') }}}) return -ERRNO_CODES.EINVAL;
1428+
1429+
return SYSCALLS.doDup(old, suggestFD);
14231430
},
14241431
__syscall331: function(which, varargs) { // pipe2
14251432
return -{{{ cDefine('ENOSYS') }}}; // unsupported feature

tests/unistd/dup.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,42 @@
1212

1313
int main() {
1414
int f, f2, f3;
15+
off_t offset;
16+
17+
EM_ASM(
18+
FS.mkdir('/working');
19+
#if NODEFS
20+
FS.mount(NODEFS, { root: '.' }, '/working');
21+
#endif
22+
FS.writeFile('/working/file', 'test');
23+
);
1524

1625
printf("DUP\n");
17-
f = open("/", O_RDONLY);
18-
f2 = open("/", O_RDONLY);
26+
f = open("/working/file", O_RDONLY);
27+
f2 = open("/working/file", O_RDONLY);
1928
f3 = dup(f);
2029
printf("errno: %d\n", errno);
2130
printf("f: %d\n", f != f2 && f != f3);
2231
printf("f2,f3: %d\n", f2 != f3);
32+
33+
// dup()ed file descriptors should share all flags and even seek position
34+
offset = lseek(f3, 0, SEEK_CUR);
35+
printf("1. f3 offset was %d. Should be 0\n", (int)offset);
36+
offset = lseek(f, 1, SEEK_SET);
37+
printf("2. f offset set to %d. Should be 1\n", (int)offset);
38+
offset = lseek(f2, 2, SEEK_SET);
39+
printf("3. f2 offset set to %d. Should be 2\n", (int)offset);
40+
offset = lseek(f, 0, SEEK_CUR);
41+
printf("4. f offset now is %d. Should be 1\n", (int)offset);
42+
offset = lseek(f2, 0, SEEK_CUR);
43+
printf("5. f2 offset now is %d. Should be 2\n", (int)offset);
44+
offset = lseek(f3, 0, SEEK_CUR);
45+
printf("6. f3 offset now is %d. Should be 1 (and not 0)\n", (int)offset);
46+
offset = lseek(f3, 3, SEEK_SET);
47+
printf("7. f3 offset set to %d. Should be 3\n", (int)offset);
48+
offset = lseek(f, 0, SEEK_CUR);
49+
printf("8. f offset now is %d. Should be 3 (and not 1)\n", (int)offset);
50+
2351
printf("close(f1): %d\n", close(f));
2452
printf("close(f2): %d\n", close(f2));
2553
printf("close(f3): %d\n", close(f3));
@@ -36,7 +64,6 @@ int main() {
3664
printf("close(f1): %d\n", close(f));
3765
printf("close(f2): %d\n", close(f2));
3866
printf("close(f3): %d\n", close(f3));
39-
printf("\n");
4067
errno = 0;
4168

4269
return 0;

tests/unistd/dup.out

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ DUP
22
errno: 0
33
f: 1
44
f2,f3: 1
5+
1. f3 offset was 0. Should be 0
6+
2. f offset set to 1. Should be 1
7+
3. f2 offset set to 2. Should be 2
8+
4. f offset now is 1. Should be 1
9+
5. f2 offset now is 2. Should be 2
10+
6. f3 offset now is 1. Should be 1 (and not 0)
11+
7. f3 offset set to 3. Should be 3
12+
8. f offset now is 3. Should be 3 (and not 1)
513
close(f1): 0
614
close(f2): 0
715
close(f3): 0

0 commit comments

Comments
 (0)