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

Added unit test for reentrancy. #95

Merged
merged 1 commit into from Sep 5, 2016
Merged

Added unit test for reentrancy. #95

merged 1 commit into from Sep 5, 2016

Conversation

@asajeffrey
Copy link
Member

asajeffrey commented Aug 9, 2016

IPC channels are reentrant, in that if we call c.send(a) and serializing a calls c.send(b), then the channel contents are b then a. (This comes up in the case of logging over channels, since serialization may include logging.)

This PR adds a unit test to make sure we don't break reentrancy.

Discussion with @nox on IRC.

@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 9, 2016

src/test.rs Outdated
#[derive(Clone, Debug, Eq, PartialEq)]
struct HasWeirdSerializer (Option<String>);

lazy_static! { static ref WEIRD_CHANNEL: (IpcSender<HasWeirdSerializer>, IpcReceiver<HasWeirdSerializer>) = ipc::channel().unwrap(); }

This comment has been minimized.

@antrik

antrik Aug 9, 2016

Contributor

A non-reentrant testcase for reentrance? Now that's just lazy! ;-)

I guess it's not really a problem, unless the test harness ever grows an ability to run the same test multiple times in parallel, which seems rather hypothetical...

@antrik
Copy link
Contributor

antrik commented Aug 9, 2016

For what it's worth, this looks good to me.

(I'm happy to see a testcase being added for obscure behaviour someone will be relying on -- a very good practice that probably should be employed more often :-) )

@jdm
Copy link
Member

jdm commented Aug 9, 2016

Travis is displeased:

     Running `rustc src/lib.rs --crate-name ipc_channel -g --test -C metadata=f57b0507e715624e -C extra-filename=-f57b0507e715624e --out-dir /Users/travis/build/servo/ipc-channel/target/debug/deps --emit=dep-info,link -L dependency=/Users/travis/build/servo/ipc-channel/target/debug/deps --extern rand=/Users/travis/build/servo/ipc-channel/target/debug/deps/librand-49a08859d086fffe.rlib --extern lazy_static=/Users/travis/build/servo/ipc-channel/target/debug/deps/liblazy_static-359f5533c970cd71.rlib --extern crossbeam=/Users/travis/build/servo/ipc-channel/target/debug/deps/libcrossbeam-95e5cb210400af41.rlib --extern bincode=/Users/travis/build/servo/ipc-channel/target/debug/deps/libbincode-6bdca1673f724e3d.rlib --extern libc=/Users/travis/build/servo/ipc-channel/target/debug/deps/liblibc-1bd8847afb79f283.rlib --extern serde=/Users/travis/build/servo/ipc-channel/target/debug/deps/libserde-652fd324488db42d.rlib`

<lazy_static macros>:2:32: 3:65 error: the trait bound `std::cell::Cell<u32>: std::marker::Sync` is not satisfied [E0277]

<lazy_static macros>:2 use std :: sync :: ONCE_INIT ; static mut $ NAME : $ crate :: lazy :: Lazy < $

                                                      ^

<lazy_static macros>:21:1: 21:40 note: in this expansion of __lazy_static_create! (defined in <lazy_static macros>)

<lazy_static macros>:4:1: 5:75 note: in this expansion of lazy_static! (defined in <lazy_static macros>)

src/test.rs:56:1: 56:135 note: in this expansion of lazy_static! (defined in <lazy_static macros>)

<lazy_static macros>:2:32: 3:65 help: run `rustc --explain E0277` to see a detailed explanation

<lazy_static macros>:2:32: 3:65 note: `std::cell::Cell<u32>` cannot be shared between threads safely 

<lazy_static macros>:2:32: 3:65 note: required because it appears within the type `platform::os::OsIpcReceiver` 

<lazy_static macros>:2:32: 3:65 note: required because it appears within the type `ipc::IpcReceiver<test::HasWeirdSerializer>` 

<lazy_static macros>:2:32: 3:65 note: required because it appears within the type `(ipc::IpcSender<test::HasWeirdSerializer>, ipc::IpcReceiver<test::HasWeirdSerializer>)` 

<lazy_static macros>:2:32: 3:65 note: required by `lazy_static::lazy::Lazy` 

error: aborting due to previous error 

error: Could not compile `ipc-channel`.
@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 10, 2016

Not sure why I'm not getting this error on my end... I'll put it in a rw mutex or some such and retry.

@antrik
Copy link
Contributor

antrik commented Aug 10, 2016

@asajeffrey on what platform(s) have you tested this? The definition of IpcReceiver is presently kinda wrong on the linux and inprocess backends (only the macos one gets it right): the definitions formally look thread-safe, which is not really true -- see discussion on #89 . I have some work in progress to fix this, which I haven't quite wrapped up yet; but once that's in, your code would fail equally on all platforms.

@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 10, 2016

The test isn't to see if it's thread-safe, it's to see if it's reentrant. Since IPC channels serialize to a fresh buffer each time, it should be reentrant.

@antrik
Copy link
Contributor

antrik commented Aug 10, 2016

@asajeffrey well, that's not what the test is about -- but since lazy_static creates a global variable, Rust enforces that whatever it holds must be thread-safe. That's not really the case for IpcReceiver.

@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 10, 2016

Indeed, since it's a global it has to be sync. Rather ironically this is exactly the use case for reentrant locks, which is what got is here in the first place. Probably easiest just to make it thread-local. I'm not at my desk today, I'll do this tomorrow.

@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 11, 2016

I made Travis happy by making the global thread-local.

Ok(HasWeirdSerializer(try!(Deserialize::deserialize(deserializer))))
}
}

This comment has been minimized.

@antrik

antrik Aug 13, 2016

Contributor

Personally I think it would be more readable to put all this stuff right before the (only) test case using it...

This comment has been minimized.

@asajeffrey

asajeffrey Aug 13, 2016

Author Member

Fair enough.

src/test.rs Outdated
let hello = HasWeirdSerializer(Some(String::from("hello")));
let (sender, receiver) = ipc::channel().unwrap();
let sender1 = sender.clone();
WEIRD_CHANNEL.with(|chan| { *chan.borrow_mut() = Some(sender1); });

This comment has been minimized.

@antrik

antrik Aug 13, 2016

Contributor

Nitpick: since this is not a move closure, it seem circuitous to do the clone() beforehand -- I think it would be cleaner simply to do Some(sender.clone()) within the closure...

This is mostly just a general hint though -- as we are talking about test code here, I wouldn't insist on fixing such a minor stylistic wrinkle :-)

This comment has been minimized.

@asajeffrey

asajeffrey Aug 13, 2016

Author Member

Okay, I'll make this change.

@antrik
Copy link
Contributor

antrik commented Aug 15, 2016

@asajeffrey thanks :-) Please squash the commits -- and then we just need someone with official reviewer status to approve it...

@asajeffrey asajeffrey force-pushed the asajeffrey:master branch from 64c177c to 34123ea Aug 15, 2016
@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 15, 2016

Squashed.

@antrik
Copy link
Contributor

antrik commented Aug 15, 2016

Meh, there is an intermittent failure it seems? This definitely shouldn't be affected by these changes...

@asajeffrey
Copy link
Member Author

asajeffrey commented Aug 15, 2016

Yes, that is odd... timeouts on unrelated tests?

@antrik
Copy link
Contributor

antrik commented Aug 20, 2016

Just to be clear: I really don't think this test failure has anything to do with this PR. Either the test case in question has intermittent failures, or there was some one-time hiccup on Travis.

@pcwalton r?

@bors-servo
Copy link
Contributor

bors-servo commented Aug 29, 2016

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

@pcwalton
Copy link
Collaborator

pcwalton commented Aug 29, 2016

Looks good once the conflicts are resolved.

@asajeffrey asajeffrey force-pushed the asajeffrey:master branch 2 times, most recently from 36af002 to 525f6d6 Sep 5, 2016
@asajeffrey asajeffrey force-pushed the asajeffrey:master branch from 525f6d6 to 3a06775 Sep 5, 2016
@asajeffrey
Copy link
Member Author

asajeffrey commented Sep 5, 2016

@bors-servo r=pcwalton

@bors-servo
Copy link
Contributor

bors-servo commented Sep 5, 2016

📌 Commit 3a06775 has been approved by pcwalton

@bors-servo
Copy link
Contributor

bors-servo commented Sep 5, 2016

Testing commit 3a06775 with merge ca63fdb...

bors-servo added a commit that referenced this pull request Sep 5, 2016
Added unit test for reentrancy.

IPC channels are reentrant, in that if we call `c.send(a)` and serializing `a` calls `c.send(b)`, then the channel contents are `b` then `a`. (This comes up in the case of logging over channels, since serialization may include logging.)

This PR adds a unit test to make sure we don't break reentrancy.

Discussion with @nox on IRC.
@bors-servo
Copy link
Contributor

bors-servo commented Sep 5, 2016

☀️ Test successful - status-appveyor, status-travis

@bors-servo bors-servo merged commit 3a06775 into servo:master Sep 5, 2016
3 checks passed
3 checks passed
continuous-integration/appveyor/pr AppVeyor build succeeded
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.

None yet

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