Skip to content

Commit a856e88

Browse files
authored
Fix dup syscalls so that they handle pipes correctly (#14808)
This fixes two problems with the `dup` system calls: 1. `dup` expects that every file descriptor has a corresponding file (so pipes and (#14640) files that have been unlinked (#15012) cannot be duplicated ). 2. The dup'd file descriptor does not share flags and position with the original file desciptor. This is a simplification of an upstream pull request that would fix this problem. https://github.com/emscripten-core/emscripten/pull/9396/files This patch is simpler than the upstream one but leaves NODERAWFS broken.
1 parent 18ce6ea commit a856e88

File tree

5 files changed

+53
-11
lines changed

5 files changed

+53
-11
lines changed

src/library_fs.js

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,9 @@ FS.staticInit();` +
400400
// SOCKFS is completed.
401401
createStream: (stream, fd_start, fd_end) => {
402402
if (!FS.FSStream) {
403-
FS.FSStream = /** @constructor */ function(){};
403+
FS.FSStream = /** @constructor */ function() {
404+
this.shared = { };
405+
};
404406
FS.FSStream.prototype = {
405407
object: {
406408
get: function() { return this.node; },
@@ -414,7 +416,15 @@ FS.staticInit();` +
414416
},
415417
isAppend: {
416418
get: function() { return (this.flags & {{{ cDefine('O_APPEND') }}}); }
417-
}
419+
},
420+
flags: {
421+
get: function() { return this.shared.flags; },
422+
set: function(val) { this.shared.flags = val; },
423+
},
424+
position : {
425+
get function() { return this.shared.position; },
426+
set: function(val) { this.shared.position = val; },
427+
},
418428
};
419429
}
420430
// clone it, so we can return an instance of FSStream

src/library_noderawfs.js

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ mergeInto(LibraryManager.library, {
4545
return { path: path, node: { id: st.ino, mode: mode, node_ops: NODERAWFS, path: path }};
4646
},
4747
createStandardStreams: function() {
48-
FS.streams[0] = { fd: 0, nfd: 0, position: 0, path: '', flags: 0, tty: true, seekable: false };
48+
FS.streams[0] = FS.createStream({ fd: 0, nfd: 0, position: 0, path: '', flags: 0, tty: true, seekable: false });
4949
for (var i = 1; i < 3; i++) {
50-
FS.streams[i] = { fd: i, nfd: i, position: 0, path: '', flags: 577, tty: true, seekable: false };
50+
FS.streams[i] = FS.createStream({ fd: i, nfd: i, position: 0, path: '', flags: 577, tty: true, seekable: false });
5151
}
5252
},
5353
// generic function for all node creation
@@ -96,16 +96,32 @@ mergeInto(LibraryManager.library, {
9696
var newMode = NODEFS.getMode(pathTruncated);
9797
var fd = suggestFD != null ? suggestFD : FS.nextfd(nfd);
9898
var node = { id: st.ino, mode: newMode, node_ops: NODERAWFS, path: path }
99-
var stream = { fd: fd, nfd: nfd, position: 0, path: path, flags: flags, node: node, seekable: true };
99+
var stream = FS.createStream({ fd: fd, nfd: nfd, position: 0, path: path, flags: flags, node: node, seekable: true });
100100
FS.streams[fd] = stream;
101101
return stream;
102102
},
103+
createStream: function(stream, fd_start, fd_end){
104+
// Call the original FS.createStream
105+
var rtn = VFS.createStream(stream, fd_start, fd_end);
106+
if (typeof rtn.shared.refcnt == "undefined") {
107+
rtn.shared.refcnf = 0;
108+
} else {
109+
rtn.shared.refcnf++;
110+
}
111+
return rtn;
112+
},
113+
closeStream: function(fd) {
114+
if (FS.streams[fd]) {
115+
FS.streams[fd].shared.refcnt--;
116+
}
117+
VFS.closeStream(fd);
118+
},
103119
close: function(stream) {
104-
if (!stream.stream_ops) {
105-
// this stream is created by in-memory filesystem
120+
FS.closeStream(stream.fd);
121+
if (!stream.stream_ops && stream.shared.refcnt === 0) {
122+
// this stream is created by in-memory filesystem
106123
fs.closeSync(stream.nfd);
107124
}
108-
FS.closeStream(stream.fd);
109125
},
110126
llseek: function(stream, offset, whence) {
111127
if (stream.stream_ops) {

src/library_syscall.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@ var SyscallsLibrary = {
279279
},
280280
__syscall_dup: function(fd) {
281281
var old = SYSCALLS.getStreamFromFD(fd);
282-
return FS.open(old.path, old.flags, 0).fd;
282+
return FS.createStream(old, 0).fd;
283283
},
284284
__syscall_pipe__deps: ['$PIPEFS'],
285285
__syscall_pipe: function(fdPtr) {
@@ -798,7 +798,7 @@ var SyscallsLibrary = {
798798
return -{{{ cDefine('EINVAL') }}};
799799
}
800800
var newStream;
801-
newStream = FS.open(stream.path, stream.flags, 0, arg);
801+
newStream = FS.createStream(stream, arg);
802802
return newStream.fd;
803803
}
804804
case {{{ cDefine('F_GETFD') }}}:
@@ -1017,7 +1017,7 @@ var SyscallsLibrary = {
10171017
if (old.fd === suggestFD) return -{{{ cDefine('EINVAL') }}};
10181018
var suggest = FS.getStream(suggestFD);
10191019
if (suggest) FS.close(suggest);
1020-
return FS.open(old.path, old.flags, 0, suggestFD, suggestFD).fd;
1020+
return FS.createStream(old, suggestFD, suggestFD + 1).fd;
10211021
},
10221022
};
10231023

tests/unistd/dup.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include <errno.h>
1010
#include <unistd.h>
1111
#include <fcntl.h>
12+
#include <emscripten.h>
13+
1214

1315
int main() {
1416
int f, f2, f3;
@@ -44,7 +46,18 @@ int main() {
4446
printf("f: %d\n", f == -1);
4547
printf("errno: %d\n", errno);
4648
printf("close(f): %d\n", close(f));
49+
printf("\n");
4750
errno = 0;
4851

52+
53+
printf("DUP2 pipe\n");
54+
int p[2];
55+
pipe(p);
56+
int g = dup2(p[0], 7);
57+
write(p[1], "abc\n", 3);
58+
char buf[5];
59+
read(g, buf, 5);
60+
// should print "buf: abc\n"
61+
printf("buf: %s\n", buf);
4962
return 0;
5063
}

tests/unistd/dup.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@ DUP2 err
1818
f: 1
1919
errno: 8
2020
close(f): -1
21+
22+
DUP2 pipe
23+
buf: abc

0 commit comments

Comments
 (0)