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

Don't leak channels. #1601

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* Runtime: fix parsing of unsigned integers (0u2147483648) (#1633, #1666)
* Runtime: fix incorrect pos_in after unmarshalling
* Runtime: make float_of_string stricter (#1609)
* Runtime: no longer leak channels
* Toplevel: fix missing primitives with separate compilation
* Compiler: fix link of packed modules with separate compilation
* Compiler: Fixed the static evaluation of some equalities (#1659)
Expand Down
86 changes: 60 additions & 26 deletions runtime/io.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@ var caml_sys_fds = new Array(3);
//Provides: caml_sys_close
//Requires: caml_sys_fds
function caml_sys_close(fd) {
var file = caml_sys_fds[fd];
if (file) file.close();
var x = caml_sys_fds[fd];
if (x && x.file) x.file.close();
delete caml_sys_fds[fd];
return 0;
}

//Provides: MlChanid
function MlChanid(id) {
this.id = id;
}

//Provides: caml_sys_open
//Requires: caml_raise_sys_error
//Requires: MlFakeFd_out
Expand All @@ -39,11 +44,16 @@ function caml_sys_close(fd) {
//Requires: fs_node_supported
//Requires: caml_sys_fds
//Requires: caml_sys_open_for_node
//Requires: MlChanid
function caml_sys_open_internal(file, idx) {
var chanid;
if (idx === undefined) {
idx = caml_sys_fds.length;
}
caml_sys_fds[idx] = file;
chanid = new MlChanid(idx);
} else if (caml_sys_fds[idx]) {
chanid = caml_sys_fds[idx].chanid;
} else chanid = new MlChanid(idx);
caml_sys_fds[idx] = { file: file, chanid: chanid };
return idx | 0;
}
function caml_sys_open(name, flags, _perms) {
Expand Down Expand Up @@ -125,41 +135,59 @@ function caml_ml_set_channel_name(chanid, name) {
}

//Provides: caml_ml_channels
var caml_ml_channels = new Array();
//Requires: MlChanid
function caml_ml_channels_state() {
this.map = new globalThis.WeakMap();
this.opened = new globalThis.Set();
}
caml_ml_channels_state.prototype.close = function (chanid) {
this.opened.delete(chanid);
};
caml_ml_channels_state.prototype.get = function (chanid) {
return this.map.get(chanid);
};
caml_ml_channels_state.prototype.set = function (chanid, val) {
if (val.opened) this.opened.add(chanid);
return this.map.set(chanid, val);
};
caml_ml_channels_state.prototype.all = function () {
return this.opened.values();
};

var caml_ml_channels = new caml_ml_channels_state();

//Provides: caml_ml_channel_get
//Requires: caml_ml_channels
function caml_ml_channel_get(id) {
return caml_ml_channels.get(id);
}

//Provides: caml_ml_channel_redirect
//Requires: caml_ml_channel_get, caml_ml_channels
function caml_ml_channel_redirect(captured, into) {
var to_restore = caml_ml_channel_get(captured);
var new_ = caml_ml_channel_get(into);
caml_ml_channels[captured] = new_; // XXX
caml_ml_channels.set(captured, new_);
return to_restore;
}

//Provides: caml_ml_channel_restore
//Requires: caml_ml_channels
function caml_ml_channel_restore(captured, to_restore) {
caml_ml_channels[captured] = to_restore; // XXX
caml_ml_channels.set(captured, to_restore);
return 0;
}

//Provides: caml_ml_channel_get
//Requires: caml_ml_channels
function caml_ml_channel_get(id) {
return caml_ml_channels[id]; // XXX
}

//Provides: caml_ml_out_channels_list
//Requires: caml_ml_channels
//Requires: caml_ml_channel_get
//Requires: caml_sys_fds
function caml_ml_out_channels_list() {
var l = 0;
for (var c = 0; c < caml_ml_channels.length; c++) {
if (
caml_ml_channels[c] &&
caml_ml_channels[c].opened &&
caml_ml_channels[c].out
)
l = [0, caml_ml_channels[c].fd, l];
var keys = caml_ml_channels.all();
for (var k of keys) {
var chan = caml_ml_channel_get(k);
if (chan.opened && chan.out) l = [0, k, l];
}
return l;
}
Expand All @@ -169,7 +197,9 @@ function caml_ml_out_channels_list() {
//Requires: caml_raise_sys_error
//Requires: caml_sys_open
function caml_ml_open_descriptor_out(fd) {
var file = caml_sys_fds[fd];
var s = caml_sys_fds[fd],
file = s.file,
chanid = s.chanid;
if (file.flags.rdonly) caml_raise_sys_error("fd " + fd + " is readonly");
var buffered = file.flags.buffered !== undefined ? file.flags.buffered : 1;
var channel = {
Expand All @@ -182,16 +212,18 @@ function caml_ml_open_descriptor_out(fd) {
buffer: new Uint8Array(65536),
buffered: buffered,
};
caml_ml_channels[channel.fd] = channel;
return channel.fd;
caml_ml_channels.set(chanid, channel);
return chanid;
}

//Provides: caml_ml_open_descriptor_in
//Requires: caml_ml_channels, caml_sys_fds
//Requires: caml_raise_sys_error
//Requires: caml_sys_open
function caml_ml_open_descriptor_in(fd) {
var file = caml_sys_fds[fd];
var s = caml_sys_fds[fd],
file = s.file,
chanid = s.chanid;
if (file.flags.wronly) caml_raise_sys_error("fd " + fd + " is writeonly");
var refill = null;
var channel = {
Expand All @@ -205,8 +237,8 @@ function caml_ml_open_descriptor_in(fd) {
buffer: new Uint8Array(65536),
refill: refill,
};
caml_ml_channels[channel.fd] = channel;
return channel.fd;
caml_ml_channels.set(chanid, channel);
return chanid;
}

//Provides: caml_ml_open_descriptor_in_with_flags
Expand Down Expand Up @@ -253,10 +285,12 @@ function caml_ml_is_binary_mode(chanid) {
//Provides: caml_ml_close_channel
//Requires: caml_ml_flush, caml_ml_channel_get
//Requires: caml_sys_close
//Requires: caml_ml_channels
function caml_ml_close_channel(chanid) {
var chan = caml_ml_channel_get(chanid);
if (chan.opened) {
chan.opened = false;
caml_ml_channels.close(chanid);
caml_sys_close(chan.fd);
chan.fd = -1;
chan.buffer = new Uint8Array(0);
Expand Down
3 changes: 2 additions & 1 deletion runtime/parsing.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ var caml_parser_trace = 0;
//Requires: caml_lex_array, caml_parser_trace,caml_jsstring_of_string
//Requires: caml_ml_output, caml_ml_string_length, caml_string_of_jsbytes
//Requires: caml_jsbytes_of_string, MlBytes
//Requires: caml_sys_fds
function caml_parse_engine(tables, env, cmd, arg) {
var ERRCODE = 256;

Expand Down Expand Up @@ -82,7 +83,7 @@ function caml_parse_engine(tables, env, cmd, arg) {

function log(x) {
var s = caml_string_of_jsbytes(x + "\n");
caml_ml_output(2, s, 0, caml_ml_string_length(s));
caml_ml_output(caml_sys_fds[2].chanid, s, 0, caml_ml_string_length(s));
}

function token_name(names, number) {
Expand Down
Loading