Skip to content

Use automatic thread joining for cargo-watch #3754

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

Merged
merged 3 commits into from
Mar 30, 2020
Merged

Conversation

matklad
Copy link
Member

@matklad matklad commented Mar 28, 2020

@matklad
Copy link
Member Author

matklad commented Mar 28, 2020

jod_thread (modeled after c++'s jthread) joins in drop. It also propagates panics to the calling thread, which is a more robust behavior.

let cmd_send = self.cmd_send.take();

// Dropping the sender finishes the thread loop
drop(cmd_send);
Copy link
Contributor

@Veetaha Veetaha Mar 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe the order of drop is crucial here, the cmd_send has to be dropped first such that the loop reading the cargo output terminates abruptly.

I this order guaranteed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, the drop order of fields is guaranteed in Rust.

@matklad
Copy link
Member Author

matklad commented Mar 28, 2020

Ah, looks like this exposed some kind of genuine race!

let recv = std::mem::replace(&mut self.message_recv, never());

// Dropping the original reciever initiates thread sub-process shutdown
drop(recv);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is unrelated, but interesting.

This bit of code rubs me the wrong way, because we base cancellation on dropping the receiver, and not sender. This is violates the unidirectional sender->receiver information flow, and is considered "bad".

It took me a while to realize what specific problem we have in this case, but I think there is a problem (mostly theoretical, which doesn't need fixing). Consider a case where cargo is slow at producing messages, and where we are waiting for the next message from Cargo. In this situation, even if we drop the receiver, we won't notice the cancellation until we get next message from Cargo (which might take a while). The "proper" way to do this would be to store a (dummy) reciever in the thread, and do a selec! on the event of receiving cargo message and on the event of dropped sender. That way, we notice cancellation immediately and can cancel Cargo without blocking.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This reminds me of that dummy receiver being the cancellation token and its appropriate sender the cancellation token source.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice observation, seems a reasonable thing to change at some point.

Copy link
Contributor

@kiljacken kiljacken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, less code is better code. Although depending on drop ordering this ways rubs me a little the wrong way.

let recv = std::mem::replace(&mut self.message_recv, never());

// Dropping the original reciever initiates thread sub-process shutdown
drop(recv);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice observation, seems a reasonable thing to change at some point.

@matklad
Copy link
Member Author

matklad commented Mar 30, 2020

bors try

bors bot added a commit that referenced this pull request Mar 30, 2020
@bors
Copy link
Contributor

bors bot commented Mar 30, 2020

try

Build failed

@matklad
Copy link
Member Author

matklad commented Mar 30, 2020

bors r+

@bors
Copy link
Contributor

bors bot commented Mar 30, 2020

@bors bors bot merged commit df8752b into rust-lang:master Mar 30, 2020
@lnicola lnicola mentioned this pull request Mar 31, 2020
@matklad matklad deleted the jod-thread branch June 25, 2020 12:16
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Sep 25, 2024
Make unused states of Reserved unrepresentable

In the [previous TB update](rust-lang/miri#3742) we discovered that the existence of `Reserved + !ty_is_freeze + protected` is undesirable.

This has the side effect of making `Reserved { conflicted: true, ty_is_freeze: false }` unreachable.
As such it is desirable that this state would also be unrepresentable.

This PR eliminates the unused configuration by changing
```rs
enum PermissionPriv {
    Reserved { ty_is_freeze: bool, conflicted: bool },
    ...
}
```
into
```rs
enum PermissionPriv {
    ReservedFrz { conflicted: bool },
    ReservedIM,
    ...
}
```
but this is not the only solution and `Reserved(Activable | Conflicted | InteriorMut)` could be discussed.
In addition to making the unreachable state not representable anymore, this change has the nice side effect of enabling `foreign_read` to no longer depend explicitly on the `protected` flag.

Currently waiting for
- `@JoJoDeveloping` to confirm that this is the same representation of `Reserved` as what is being implemented in simuliris,
- `@RalfJung` to approve that this does not introduce too much overhead in the trusted codebase.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants