Skip to content

Commit 54ed5dc

Browse files
authored
fix(inspector): avoid double RefCell borrow (#1195)
Fixing some of the fall out from #1193. Testing in CLI it turned out that there's a double RefCell borrow panic occuring, when running the REPL - when the exception was raised when evaluating an expression - and said expression was evaluated as part of dispatching an inspector message - the `op_dispatch_exception` op was called that tries to mutable borrow the inspector instance. This is now avoided by storing `SessionContainer` in the `LocalInspectorSession`, instead of `JsRuntimeInspector`. This will be further simplified in follow up PRs like #1192.
1 parent 63d156c commit 54ed5dc

File tree

1 file changed

+39
-41
lines changed

1 file changed

+39
-41
lines changed

core/inspector.rs

Lines changed: 39 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ pub struct JsRuntimeInspector {
8585
v8_inspector_client: v8::inspector::V8InspectorClientBase,
8686
v8_inspector: Rc<RefCell<v8::UniquePtr<v8::inspector::V8Inspector>>>,
8787
new_session_tx: UnboundedSender<InspectorSessionProxy>,
88-
sessions: RefCell<SessionContainer>,
88+
sessions: Rc<RefCell<SessionContainer>>,
8989
flags: RefCell<InspectorFlags>,
9090
waker: Arc<InspectorWaker>,
9191
deregister_tx: Option<oneshot::Sender<()>>,
@@ -194,7 +194,9 @@ impl JsRuntimeInspector {
194194
let self__ = Rc::new(RefCell::new(Self {
195195
v8_inspector_client,
196196
v8_inspector: Default::default(),
197-
sessions: RefCell::new(SessionContainer::temporary_placeholder()),
197+
sessions: Rc::new(
198+
RefCell::new(SessionContainer::temporary_placeholder()),
199+
),
198200
new_session_tx,
199201
flags: Default::default(),
200202
waker,
@@ -207,10 +209,10 @@ impl JsRuntimeInspector {
207209
self_.v8_inspector = Rc::new(RefCell::new(
208210
v8::inspector::V8Inspector::create(scope, &mut *self_).into(),
209211
));
210-
self_.sessions = RefCell::new(SessionContainer::new(
212+
self_.sessions = Rc::new(RefCell::new(SessionContainer::new(
211213
self_.v8_inspector.clone(),
212214
new_session_rx,
213-
));
215+
)));
214216

215217
// Tell the inspector about the main realm.
216218
let context_name = v8::inspector::StringView::from(&b"main realm"[..]);
@@ -247,16 +249,6 @@ impl JsRuntimeInspector {
247249
*self.is_dispatching_message.borrow()
248250
}
249251

250-
pub fn dispatch_message_from_frontend(
251-
&self,
252-
session_id: i32,
253-
message: String,
254-
) {
255-
let mut sessions = self.sessions.borrow_mut();
256-
let session = sessions.local.get_mut(&session_id).unwrap();
257-
session.dispatch_message(message);
258-
}
259-
260252
pub fn context_destroyed(
261253
&mut self,
262254
scope: &mut HandleScope,
@@ -424,16 +416,15 @@ impl JsRuntimeInspector {
424416
/// established a websocket connection.
425417
pub fn wait_for_session(&mut self) {
426418
loop {
427-
match self.sessions.get_mut().established.iter_mut().next() {
428-
Some(_session) => {
429-
self.flags.get_mut().waiting_for_session = false;
430-
break;
431-
}
432-
None => {
433-
self.flags.get_mut().waiting_for_session = true;
434-
let _ = self.poll_sessions(None).unwrap();
435-
}
436-
};
419+
if let Some(_session) =
420+
self.sessions.borrow_mut().established.iter_mut().next()
421+
{
422+
self.flags.get_mut().waiting_for_session = false;
423+
break;
424+
} else {
425+
self.flags.get_mut().waiting_for_session = true;
426+
let _ = self.poll_sessions(None).unwrap();
427+
}
437428
}
438429
}
439430

@@ -445,13 +436,14 @@ impl JsRuntimeInspector {
445436
/// execution.
446437
pub fn wait_for_session_and_break_on_next_statement(&mut self) {
447438
loop {
448-
match self.sessions.get_mut().established.iter_mut().next() {
449-
Some(session) => break session.break_on_next_statement(),
450-
None => {
451-
self.flags.get_mut().waiting_for_session = true;
452-
let _ = self.poll_sessions(None).unwrap();
453-
}
454-
};
439+
if let Some(session) =
440+
self.sessions.borrow_mut().established.iter_mut().next()
441+
{
442+
break session.break_on_next_statement();
443+
} else {
444+
self.flags.get_mut().waiting_for_session = true;
445+
let _ = self.poll_sessions(None).unwrap();
446+
}
455447
}
456448
}
457449

@@ -478,7 +470,7 @@ impl JsRuntimeInspector {
478470
callback: InspectorSessionSend,
479471
options: InspectorSessionOptions,
480472
) -> LocalInspectorSession {
481-
let session_id = {
473+
let (session_id, sessions) = {
482474
let self_ = inspector.borrow_mut();
483475

484476
let inspector_session = InspectorSession::new(
@@ -498,10 +490,10 @@ impl JsRuntimeInspector {
498490
};
499491

500492
take(&mut self_.flags.borrow_mut().waiting_for_session);
501-
session_id
493+
(session_id, self_.sessions.clone())
502494
};
503495

504-
LocalInspectorSession::new(session_id, inspector)
496+
LocalInspectorSession::new(session_id, sessions)
505497
}
506498
}
507499

@@ -606,6 +598,15 @@ impl SessionContainer {
606598
local: HashMap::new(),
607599
}
608600
}
601+
602+
pub fn dispatch_message_from_frontend(
603+
&mut self,
604+
session_id: i32,
605+
message: String,
606+
) {
607+
let session = self.local.get_mut(&session_id).unwrap();
608+
session.dispatch_message(message);
609+
}
609610
}
610611

611612
struct InspectorWakerInner {
@@ -857,24 +858,21 @@ impl InspectorPostMessageError {
857858
///
858859
/// Does not provide any abstraction over CDP messages.
859860
pub struct LocalInspectorSession {
860-
inspector: Rc<RefCell<JsRuntimeInspector>>,
861+
sessions: Rc<RefCell<SessionContainer>>,
861862
session_id: i32,
862863
}
863864

864865
impl LocalInspectorSession {
865-
pub fn new(
866-
session_id: i32,
867-
inspector: Rc<RefCell<JsRuntimeInspector>>,
868-
) -> Self {
866+
pub fn new(session_id: i32, sessions: Rc<RefCell<SessionContainer>>) -> Self {
869867
Self {
870-
inspector,
868+
sessions,
871869
session_id,
872870
}
873871
}
874872

875873
pub fn dispatch(&mut self, msg: String) {
876874
self
877-
.inspector
875+
.sessions
878876
.borrow_mut()
879877
.dispatch_message_from_frontend(self.session_id, msg);
880878
}

0 commit comments

Comments
 (0)