Skip to content

Commit 1afd9c1

Browse files
committed
Restore Send bound on task closures
To avoid sending objects with implementations sensitive to thread state (id, thread-local storage, etc) Requires dev tree-sitter which adds `Send` and `Sync` bounds to a bunch of types.
1 parent 065f298 commit 1afd9c1

File tree

7 files changed

+47
-27
lines changed

7 files changed

+47
-27
lines changed

Cargo.lock

Lines changed: 20 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
[workspace]
22

3+
# Was necessary after switching to dev tree-sitter to fix this warning:
4+
# > some crates are on edition 2021 which defaults to `resolver = "2"`, but
5+
# > virtual workspaces default to `resolver = "1"`
6+
resolver = "2"
7+
38
members = [
49
"crates/amalthea",
510
"crates/ark",

crates/ark/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ nix = { version = "0.26.2", features = ["signal"] }
3333
notify = "6.0.0"
3434
once_cell = "1.17.1"
3535
parking_lot = "0.12.1"
36-
regex = "1.7.1"
36+
regex = "1.10.0"
3737
reqwest = { version = "0.11.20", features = ["json"] }
3838
ropey = "1.6.0"
3939
rust-embed = "8.0.0"
@@ -43,8 +43,8 @@ serde_json = "1.0.94"
4343
stdext = { path = "../stdext" }
4444
tokio = { version = "1.26.0", features = ["full"] }
4545
tower-lsp = "0.19.0"
46-
tree-sitter = "0.20.9"
47-
tree-sitter-r = { git = "https://github.com/r-lib/tree-sitter-r", branch = "next" }
46+
tree-sitter = { git = "https://github.com/tree-sitter/tree-sitter" }
47+
tree-sitter-r = { git = "https://github.com/r-lib/tree-sitter-r", branch = "bugfix/update" }
4848
uuid = "1.3.0"
4949
url = "2.4.1"
5050
walkdir = "2"

crates/ark/src/r_task.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ type SharedOption<T> = Arc<Mutex<Option<T>>>;
2626
pub fn r_task<'env, F, T>(f: F) -> T
2727
where
2828
F: FnOnce() -> T,
29-
F: 'env,
30-
T: 'env,
29+
F: 'env + Send,
30+
T: 'env + Send,
3131
{
3232
// Escape hatch for unit tests
3333
if unsafe { R_TASK_BYPASS } {
@@ -62,7 +62,7 @@ where
6262
};
6363

6464
// Move `f` to heap and erase its lifetime
65-
let closure: Box<dyn FnOnce() + 'env> = Box::new(closure);
65+
let closure: Box<dyn FnOnce() + 'env + Send> = Box::new(closure);
6666
let closure: Box<dyn FnOnce() + Send + 'static> = unsafe { std::mem::transmute(closure) };
6767

6868
// Channel to communicate completion status of the task/closure

crates/ark/tests/environment.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ fn test_environment_list() {
6969
let incoming_tx = comm.incoming_tx.clone();
7070
let outgoing_rx = comm.outgoing_rx.clone();
7171
r_task(|| {
72-
let test_env_view = RObject::view(test_env.sexp);
72+
let test_env_view = RObject::view(*test_env);
7373
REnvironment::start(test_env_view, comm.clone(), comm_manager_tx.clone());
7474
});
7575

@@ -90,7 +90,7 @@ fn test_environment_list() {
9090
// variables with the new variable in it.
9191
r_task(|| unsafe {
9292
let sym = r_symbol!("everything");
93-
Rf_defineVar(sym, Rf_ScalarInteger(42), test_env.sexp);
93+
Rf_defineVar(sym, Rf_ScalarInteger(42), *test_env);
9494
});
9595

9696
// Request that the environment be refreshed
@@ -122,8 +122,8 @@ fn test_environment_list() {
122122

123123
// Create another variable
124124
r_task(|| unsafe {
125-
r_envir_set("nothing", Rf_ScalarInteger(43), test_env.sexp);
126-
r_envir_remove("everything", test_env.sexp);
125+
r_envir_set("nothing", Rf_ScalarInteger(43), *test_env);
126+
r_envir_remove("everything", *test_env);
127127
});
128128

129129
// Simulate a prompt signal
@@ -173,17 +173,17 @@ fn test_environment_list() {
173173

174174
// test the env is now empty
175175
r_task(|| unsafe {
176-
let contents = RObject::new(R_lsInternal(test_env.sexp, Rboolean_TRUE));
176+
let contents = RObject::new(R_lsInternal(*test_env, Rboolean_TRUE));
177177
assert_eq!(Rf_length(*contents), 0);
178178
});
179179

180180
// Create some more variables
181181
r_task(|| unsafe {
182182
let sym = r_symbol!("a");
183-
Rf_defineVar(sym, Rf_ScalarInteger(42), test_env.sexp);
183+
Rf_defineVar(sym, Rf_ScalarInteger(42), *test_env);
184184

185185
let sym = r_symbol!("b");
186-
Rf_defineVar(sym, Rf_ScalarInteger(43), test_env.sexp);
186+
Rf_defineVar(sym, Rf_ScalarInteger(43), *test_env);
187187
});
188188

189189
// Simulate a prompt signal

crates/harp/src/environment.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,11 @@ pub struct Binding {
104104
}
105105

106106
// For sending to main thread as R task
107-
unsafe impl Send for Binding {}
108107
unsafe impl Sync for Binding {}
109108

109+
// FIXME: This should only be Sync
110+
unsafe impl Send for Binding {}
111+
110112
impl Binding {
111113
pub fn new(env: SEXP, frame: SEXP) -> Self {
112114
unsafe {

crates/harp/src/object.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,12 +214,14 @@ impl Drop for RObject {
214214
}
215215
}
216216

217-
// RObjects are not inherently thread-safe since they wrap a raw pointer, but we
218-
// allow them to be sent across threads because we require the acquisition of a
219-
// lock on the outer R interpreter (see `r_task()`) before using them.
220-
unsafe impl Send for RObject {}
217+
// References to RObjects are safe to send over threads but the actual
218+
// object should remain on the R thread at all times. We can only `drop()`
219+
// them on the R thread since that calls the R API.
221220
unsafe impl Sync for RObject {}
222221

222+
// FIXME: This should only be Sync
223+
unsafe impl Send for RObject {}
224+
223225
impl Deref for RObject {
224226
type Target = SEXP;
225227
fn deref(&self) -> &Self::Target {

0 commit comments

Comments
 (0)