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

Constellation manages script thread lifetime #14052

Conversation

@asajeffrey
Copy link
Member

asajeffrey commented Nov 3, 2016

Yet another step towards fixing #633...

At the moment, script threads are responsible for killing themselves when they have no more pipelines to manage. This is fine right now, because script threads have a root pipeline: once it is closed, everything is closed. It's not fine once we fix #633 because there's a race condition where the constellation could kill the last pipeline in a script thread, then open a new one in the same script thread.

We can't have the constellation block on the script thread, waiting to make sure a pipeline is created, since this could introduce deadlock. The easiest solution is to have the constellation manage the script thread lifetime: when the constellation discovers that a script thread is not managing any live pipelines, it closes the script thread, and updates its own state.

Most of the commits are from #14013, its just "Script thread lifetime is now managed by the constellation." (9ac6e4d) that's new.

cc @jdm @ConnorGBrewster


  • ./mach build -d does not report any errors
  • ./mach test-tidy does not report any errors
  • These changes do not require tests because refactoring

This change is Reviewable

@highfive
Copy link

highfive commented Nov 3, 2016

Heads up! This PR modifies the following files:

  • @fitzgen: components/script/dom/htmliframeelement.rs, components/script/dom/document.rs, components/script/webdriver_handlers.rs, components/script/dom/node.rs, components/script/dom/browsingcontext.rs, components/script/dom/storage.rs, components/script_traits/script_msg.rs, components/script_traits/script_msg.rs, components/script/document_loader.rs, components/script/dom/nodelist.rs, components/script/script_thread.rs, components/script_traits/lib.rs, components/script_traits/lib.rs, components/script/devtools.rs
  • @KiChjang: components/script/dom/htmliframeelement.rs, components/script/dom/document.rs, components/script/webdriver_handlers.rs, components/net/http_loader.rs, components/script/dom/node.rs, components/script/dom/browsingcontext.rs, components/script/dom/storage.rs, components/script_traits/script_msg.rs, components/script_traits/script_msg.rs, components/script/document_loader.rs, components/script/dom/nodelist.rs, components/script/script_thread.rs, components/script_traits/lib.rs, components/script_traits/lib.rs, components/script/devtools.rs
@highfive
Copy link

highfive commented Nov 3, 2016

warning Warning warning

  • These commits modify unsafe code. Please review it carefully!
@asajeffrey asajeffrey force-pushed the asajeffrey:constellation-manages-script-thread-lifetime branch from 9ac6e4d to 774172b Nov 3, 2016
@asajeffrey
Copy link
Member Author

asajeffrey commented Nov 3, 2016

Rebased.

Copy link
Member

nox left a comment

Could you write in the second commit message why switching to a set of documents was needed?

self.offset = self.offset + 1;
result
}
}

This comment has been minimized.

@nox

nox Nov 4, 2016

Member

Why do you need this iterator? We shouldn't use NodeList outside from other DOM stuff IMO, it's quite inefficient.

Also, this iterator continues to increment offset for nothing if self.nodes.Item(self.offset) returned None, and it doesn't provide a size hint so it's probably used inefficiently.

},
DevtoolScriptControlMsg::GetRootNode(id, reply) =>
devtools::handle_get_root_node(&context, id, reply),
devtools::handle_get_root_node(&*documents, id, reply),

This comment has been minimized.

@nox

nox Nov 4, 2016

Member

Nit: why is the * suddenly needed?

pub struct ScriptChan {
chan: IpcSender<ConstellationControlMsg>,
dont_send_or_sync: PhantomData<Rc<()>>,
}

This comment has been minimized.

@nox

nox Nov 4, 2016

Member

This seems quite dangerous to me. Could we not rely on Drop? What happens if that value is forgotten?

This comment has been minimized.

@jdm

jdm Nov 7, 2016

Member

I disagree that it seems dangerous, but I don't understand why it's needed. Whether it's Sync or not seems immaterial, since we just seem to care that ownership can't be transferred to some non-constellation thread. However, if it's only constructed via the new method and that only returns Rc, this seems to be redundant.

This comment has been minimized.

@asajeffrey

asajeffrey Nov 8, 2016

Author Member

The dont_send_or_sync isn't necessary, it's just there to make sure that any messages that are sent on this channel come from the constellation thread. I could just remove it.

@asajeffrey
Copy link
Member Author

asajeffrey commented Nov 4, 2016

@nox: are you commenting on the changes in #14013? This PR is just the last commit. I love dependent PRs, I love dependent PRs...

@asajeffrey asajeffrey force-pushed the asajeffrey:constellation-manages-script-thread-lifetime branch from 774172b to 354501b Nov 4, 2016
@nox
Copy link
Member

nox commented Nov 4, 2016

r? @jdm

@highfive highfive assigned jdm and unassigned nox Nov 4, 2016
debug!("Exiting script thread.");

while let Some(pipeline_id) = self.incomplete_loads.borrow().iter().next().map(|load| load.pipeline_id)
.or_else(|| self.documents.borrow().iter().next().map(|doc| doc.global().pipeline_id()))

This comment has been minimized.

@jdm

jdm Nov 7, 2016

Member
let mut pipelines = self.incomplete_loads.borrow().iter().map(|load| load.pipeline_id);
let mut pipelines = self.documents.borrow().iter().map(|doc| doc.global().pipeline_id()).zip(pipelines);
while let Some(pipeline_id) = pipelines.next() {

Also, if we add the ability to iterate over the keys of the documents object, the second iterator becomes clearer.

This comment has been minimized.

@asajeffrey

asajeffrey Nov 8, 2016

Author Member

The problem is we can't have the iterator borrowed while we call handle_exit_pipeline_msg, since it mutably borrows self.documents and self.incomplete_loads.

This comment has been minimized.

@jdm

jdm Nov 8, 2016

Member

I'm actually surprised that this works as written, since calling iter() should cause a new iterator to be created every time...

This comment has been minimized.

@jdm

jdm Nov 8, 2016

Member

A more workable option is to create a vector from the original iterators and iterate over that.

This comment has been minimized.

@asajeffrey

asajeffrey Nov 8, 2016

Author Member

There is new iterator each time, but that's okay because handle_exit_pipeline_msg removes the entry, so we don't end up infinitely looping. We can just collect the iterators into a vector though, that is probably easier to read.

pub fn send(&self, msg: ConstellationControlMsg) -> Result<(), IOError> {
self.chan.send(msg)
}
pub fn new(chan: IpcSender<ConstellationControlMsg>) -> ScriptChan {

This comment has been minimized.

@jdm

jdm Nov 7, 2016

Member

Why not make this return Rc<ScriptChan>?

This comment has been minimized.

@asajeffrey

asajeffrey Nov 8, 2016

Author Member

Done.

pub struct ScriptChan {
chan: IpcSender<ConstellationControlMsg>,
dont_send_or_sync: PhantomData<Rc<()>>,
}

This comment has been minimized.

@jdm

jdm Nov 7, 2016

Member

I disagree that it seems dangerous, but I don't understand why it's needed. Whether it's Sync or not seems immaterial, since we just seem to care that ownership can't be transferred to some non-constellation thread. However, if it's only constructed via the new method and that only returns Rc, this seems to be redundant.

@bors-servo
Copy link
Contributor

bors-servo commented Nov 8, 2016

The latest upstream changes (presumably #14013) made this pull request unmergeable. Please resolve the merge conflicts.

@jdm
Copy link
Member

jdm commented Nov 8, 2016

Looks good!

@jdm
jdm approved these changes Nov 8, 2016
@asajeffrey asajeffrey force-pushed the asajeffrey:constellation-manages-script-thread-lifetime branch from d27a481 to 08effa7 Nov 8, 2016
@asajeffrey
Copy link
Member Author

asajeffrey commented Nov 8, 2016

Squashed. @bors-servo r=jdm

@bors-servo
Copy link
Contributor

bors-servo commented Nov 8, 2016

📌 Commit 08effa7 has been approved by jdm

@notriddle notriddle force-pushed the asajeffrey:constellation-manages-script-thread-lifetime branch from 08effa7 to 0e7ffaf Nov 9, 2016
@notriddle
Copy link
Contributor

notriddle commented Nov 9, 2016

@bors-servo r=jdm

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

📌 Commit 0e7ffaf has been approved by jdm

@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

Testing commit 0e7ffaf with merge 13009fe...

bors-servo added a commit that referenced this pull request Nov 9, 2016
…-lifetime, r=jdm

Constellation manages script thread lifetime

<!-- Please describe your changes on the following line: -->

Yet another step towards fixing #633...

At the moment, script threads are responsible for killing themselves when they have no more pipelines to manage. This is fine right now, because script threads have a root pipeline: once it is closed, everything is closed. It's not fine once we fix #633 because there's a race condition where the constellation could kill the last pipeline in a script thread, then open a new one in the same script thread.

We can't have the constellation block on the script thread, waiting to make sure a pipeline is created, since this could introduce deadlock. The easiest solution is to have the constellation manage the script thread lifetime: when the constellation discovers that a script thread is not managing any live pipelines, it closes the script thread, and updates its own state.

Most of the commits are from #14013, its just "Script thread lifetime is now managed by the constellation." (9ac6e4d) that's new.

cc @jdm @ConnorGBrewster

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes do not require tests because refactoring

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/14052)
<!-- Reviewable:end -->
@bors-servo
Copy link
Contributor

bors-servo commented Nov 9, 2016

@bors-servo bors-servo merged commit 0e7ffaf into servo:master Nov 9, 2016
2 of 3 checks passed
2 of 3 checks passed
continuous-integration/appveyor/pr AppVeyor build failed
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
homu Test successful
Details
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

6 participants
You can’t perform that action at this time.