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

Windows #233

Closed
wants to merge 113 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
113 commits
Select commit Hold shift + click to select a range
cf2ecd9
tests: cleanup: Avoid `.pop().unwrap()` in cross_process_sender_trans…
vvuk Sep 9, 2016
4c6a096
tests: Add variants of cross-process test, using `spawn()`
vvuk Sep 9, 2016
03687e3
Add inception channel-in-channel multi-process transfer test
vvuk Dec 15, 2016
1c9f7ab
tests: Introduce `which` parameter in `get_channel_name_arg()` helper
antrik Jul 12, 2017
1f22aa0
tests: Move `get_channel_name_arg()` helper to `src/test.rs`
antrik Jul 12, 2017
ad1b9ff
tests: Introduce `cross_process_embedded_senders_spawn()`
antrik Jul 12, 2017
e4c83d1
tests: cleanup: Streamline structure of `_server()` helpers
antrik Jul 12, 2017
50fe7c4
tests: cleanup: Introduce a common `spawn_server()` helper function
antrik Jul 26, 2017
d52be62
tests: cleanup: Avoid need for separate `_server()` pseudo-tests
antrik Jul 26, 2017
3347fc1
Implement ipc-channel on Windows
vvuk Sep 9, 2016
57bc52e
appveyor.yml: Restore testing `inprocess` back-end, not only native one
antrik Nov 5, 2017
3eb82d9
tests: Split out SHM object equality check
antrik Sep 23, 2017
ab99734
windows: fix warning: `reader` doesn't need to be mutable
antrik Sep 23, 2017
75763d0
windows: cleanup: Change suitable plain comments into doc comments
antrik Sep 23, 2017
0e48d3f
windows: cleanup: Use more standard indentation for macro
antrik Sep 23, 2017
19af7c9
windows: Move out original handle in `to_receiver()` and `to_sender()`
antrik Sep 24, 2017
db07779
windows: Drop unnecessary `&mut self` in a few places
antrik Sep 24, 2017
80ee2d7
windows: cleanup: Switch methods for a more logical order
antrik Sep 24, 2017
505a3df
windows: Mark `notify_completion()` as unsafe
antrik Sep 24, 2017
27376c3
windows: Widen too narrow `unsafe` block
antrik Sep 24, 2017
4cc8401
windows: Drop custom `GetMessageResult` type
antrik Sep 24, 2017
712c37a
windows: More defensive receive buffer handling
antrik Sep 24, 2017
1c33a04
[RemoveMe] Temporarily disable most CI targets
antrik Sep 24, 2017
6642fbe
windows: Add explanation why the `ov` structure needs to be boxed
antrik Sep 27, 2017
82fc077
windows: Implement `Drop` for `MessageReader`
antrik Sep 27, 2017
8a546b8
windows: Consume reader immediately when moving out handle
antrik Sep 28, 2017
5f70a30
windows: Take ownership of handle in `move_handle_to_process()`
antrik Sep 24, 2017
5649048
windows: Assert valid state before consuming receiver
antrik Sep 30, 2017
80a2898
windows: Don't duplicate handle when consuming receiver
antrik Sep 30, 2017
5934d72
windows: Remove bogus explicit `impl Send` for `OsIpcSender`
antrik Sep 24, 2017
b14fa51
windows: Add a comment explaining the `impl Send` on `OsIpcReceiver`
antrik Sep 30, 2017
c0f3fd8
windows: cleanup: Use enum rather than anonymous bool for blocking mo…
antrik Sep 30, 2017
e27cfaf
windows: Improve placement of comments in `receive_message()`
antrik Oct 1, 2017
65699b1
windows: Add checks and warnings regarding dangers of `ov` and `read_…
antrik Oct 6, 2017
dfcae21
windows: Shrink unnecessarily wide `unsafe` block
antrik Oct 6, 2017
7a600b7
windows: Minor comment fix
antrik Oct 6, 2017
56c0f30
windows: cleanup: More straightforward use of default match case
antrik Oct 6, 2017
2265c29
windows: Take `WinHandle` rather than `HANDLE` in `write_msg()` and `…
antrik Oct 6, 2017
216d1ce
windows: cleanup: Use helper variable consistently
antrik Oct 7, 2017
91e95bf
windows: cleanup: Merge `write_msg()` functionality into `write_buf()`
antrik Oct 7, 2017
3c921a7
windows: Shrink an unnecessarily wide `unsafe` block
antrik Oct 7, 2017
ec03bd1
windows: Fix overly eager size check
antrik Oct 7, 2017
b50dc8b
windows: Fix another overly eager size check
antrik Oct 7, 2017
42e8304
windows: Revamp send buffer construction to minimise `unsafe`
antrik Oct 7, 2017
d70b8c9
windows: Remove trivial `MessageHeader::size()` helper
antrik Oct 7, 2017
f742ceb
windows: Turn `MessageHeader` into normal struct
antrik Oct 7, 2017
9e28ebe
windows: Check for errors on SHM unmapping
antrik Oct 7, 2017
4656176
windows: Check for errors on file handle closing
antrik Oct 7, 2017
776dd31
windows: Add check to make sure we don't leak `OsOpaqueIpcChannel`
antrik Oct 7, 2017
f4987b5
windows: Fix SHM mapping for areas larger than 2^32
antrik Oct 7, 2017
ad4e40d
windows: Derive `PartialEq` on `WinError`
antrik Oct 7, 2017
f801fbe
windows: cleanup: Don't intersperse method impls with free-standing f…
antrik Oct 7, 2017
9b288b7
windows: cleanup: `start_read()`: Use `match` for error handling
antrik Oct 8, 2017
15e8346
windows: cleanup: `start_read()`: Consistenly use explicit `return`
antrik Oct 13, 2017
888773d
windows: cleanup: `start_read()`: Merge handling of identical cases
antrik Oct 13, 2017
6e406d8
windows: cleanup: `start_read()`: Switch cases for more logical order
antrik Oct 13, 2017
f3a0c1d
windows: cleanup: `start_read()`: Construct a temporary `Result<>`
antrik Oct 13, 2017
608a0f5
windows: cleanup: Drop redundant comment part
antrik Oct 8, 2017
8163de2
windows: Fix misplaced comment
antrik Oct 8, 2017
fa9ecb2
windows: Drop bogus `Result<>` from `notify_completion()`
antrik Oct 8, 2017
b41423c
windows: Drop bogus comment
antrik Oct 16, 2017
1eb97b8
windows: Introduce `MessageReader.fetch_async_result()` helper method
antrik Oct 16, 2017
db945e4
windows: Move `Send` declaration from `OsIpcReceiver` to `MessageReader`
antrik May 10, 2018
41e5b9c
windows: cleanup: Consume reader in `read_raw_sized()`
antrik Oct 16, 2017
3de41e9
windows: Avoid code duplication in `read_raw_sized()`
antrik Oct 16, 2017
bcf026f
windows: Take `WinHandle` rather than `HANDLE` in `add_to_iocp()`
antrik Oct 19, 2017
21c92ab
windows: Comment on boxing `OVERLAPPED` inside `OsIpcReceiver.accept()`
antrik Oct 21, 2017
3cc52e8
windows: cleanup: `OsIpcReceiver.accept()`: Unwrap handle at actual u…
antrik Oct 28, 2017
3fa1de2
windows: Fix a misleading (outdated?) comment
antrik Oct 29, 2017
cc31739
windows: cleanup: Use `if let` rather than `is_some()` + `unwrap()`
antrik Oct 29, 2017
f6c276c
windows: cleanup: More idiomatic search code
antrik Oct 29, 2017
1dc0270
windows: cleanup: Use `if let` rather than one-arm `match`
antrik Oct 31, 2017
cfeab5f
windows: Don't explicitly set `ErrorKind::BrokenPipe` on closed sender
antrik Nov 5, 2017
686960f
windows: cleanup: Use `while let` rather than `loop` + `match`
antrik Nov 12, 2017
b1d2b97
windows: refactor: More straightforward "closed" status handling
antrik Nov 12, 2017
fbd8632
windows: Don't delay "sender closed" notification from `select()`
antrik Nov 13, 2017
6687016
windows: Handle channel closed events directly where possible
antrik Nov 13, 2017
91b4331
windows: cleanup: Simplify control flow
antrik Apr 30, 2018
17c7901
windows: Introduce `closed_readers` vector instead of `MessageReader.…
antrik Apr 29, 2018
4f0d5e2
windows: cleanup: Rename `WinHandle.take()` to `take_raw()`
antrik Apr 29, 2018
fb768aa
windows: cleanup: More idiomatic `for` loops
antrik Apr 29, 2018
5374198
windows: cleanup: More idiomatic use of tuples
antrik Apr 29, 2018
4d1dd1d
windows: Use `WinHandle` in more places
antrik Apr 29, 2018
7119bee
windows: refactor: (Re-)introduce `WinHandle.take()` with expected me…
antrik Apr 29, 2018
143cce1
windows: Use explicit `as_raw()` on WinHandle instead of `deref()`
antrik Apr 30, 2018
8b9db47
windows: cleanup: Simpler casting for `completion_key`
antrik Apr 30, 2018
da172ac
windows: cleanup: Tighten scope of `nbytes` local variable
antrik May 1, 2018
3627454
windows: cleanup: Streamline handling of reader list in `select()`
antrik May 1, 2018
d070683
windows: Fix `unsafe` coverage in `OsIpcReceiverSet.select()`
antrik May 1, 2018
f36ffa4
windows: cleanup: Be more explicit about completion key creation
antrik Apr 30, 2018
e90a90f
windows: Rename `set_id` to `entry_id`
antrik Apr 30, 2018
55afd64
windows: cleanup: More idiomatic handling of `io_err`
antrik May 5, 2018
5062c26
windows: cleanup: Pass status as a proper `Result<>`
antrik May 5, 2018
6831ca2
windows: cleanup: `match` on errors in `notify_completion()`
antrik May 5, 2018
2b6c93e
windows: More defensive `read_in_progress` handling
antrik May 6, 2018
48a33db
windows: Make `MessageReader.ov` optional
antrik May 6, 2018
b9c3004
windows: Drop explicit `read_in_progress` flag
antrik May 6, 2018
05fd68d
windows: Avoid leaking unsafety outside `unsafe` blocks
antrik May 7, 2018
b1eb0c9
windows: Clarify comment about `start_read()` for receivers in sets
antrik May 15, 2018
eccd9d4
windows: Put `ov` and `buf` in the same `AliasedCell<>`
antrik May 14, 2018
86ea0f1
windows: Don't ignore `CancelIoEx()` errors
antrik May 15, 2018
66aa634
windows: Don't panic on unknown errors in `notify_completion()`
antrik May 15, 2018
54e3faf
windows: refactor: Split out `OsIpcReceiverSet.fetch_iocp_result()`
antrik May 19, 2018
b85e676
windows: Make `cancel_io()` sound
antrik May 19, 2018
0758099
[RemoveMe] Temporarily restore all CI targets using `unix` back-end
antrik May 30, 2018
3481ef1
WIP: threaded fragment tests
antrik Jun 7, 2018
12e03b9
windows: Properly hide all `win32-trace` code behind conditionals
antrik Jun 8, 2018
0aefbb9
windows: Introduce `MessageReader.get_raw_handle()` debug helper
antrik Jun 8, 2018
1a023e9
windows: Move `handle` into `AsyncData` as well
antrik May 21, 2018
6e678a7
fixup! Implement ipc-channel on Windows
angelortiz1007 Jun 24, 2019
6a51744
Update for Rust 2018.
angelortiz1007 Jun 24, 2019
237e026
Migrated ipc-channel to use winapi version 3. Removed kernel3
angelortiz1007 Jun 26, 2019
24a2207
Test of GetNamedPipeClientSessionId() and GetNamedPipeClientSessionId…
angelortiz1007 Jul 3, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,13 @@ rust:

os:
- linux
- osx

env:
global:
- RUST_BACKTRACE=1
matrix:
- FEATURES="unstable"
- FEATURES="unstable force-inprocess"

matrix:
include:
- os: linux
env: FEATURES="unstable memfd"
- FEATURES="unstable memfd"

script:
- cargo build --features "$FEATURES"
Expand Down
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ force-inprocess = []
memfd = ["sc"]
unstable = []
async = ["futures-preview", "futures-test-preview"]
win32-trace = []

[dependencies]
bincode = "1"
Expand All @@ -32,3 +33,6 @@ sc = { version = "0.2.2", optional = true }

[dev-dependencies]
crossbeam = "0.2"

[target.'cfg(target_os = "windows")'.dependencies]
winapi = {version = "0.3.7", features = ["minwindef", "ioapiset", "memoryapi", "namedpipeapi", "handleapi", "fileapi", "impl-default"]}
5 changes: 2 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ environment:
RUST_BACKTRACE: 1
matrix:
- TARGET: x86_64-pc-windows-msvc
- TARGET: i686-pc-windows-msvc
- TARGET: i686-pc-windows-gnu
FEATURES: "unstable"
install:
- ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-nightly-${env:TARGET}.exe"
- rust-nightly-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
Expand All @@ -14,4 +13,4 @@ install:
build: false

test_script:
- 'cargo test --verbose --features "unstable"'
- cargo test --verbose --features "%FEATURES%"
4 changes: 4 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ extern crate futures_test;
#[cfg(feature = "async")]
pub mod asynch;

#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
extern crate winapi;


pub mod ipc;
pub mod platform;
pub mod router;
Expand Down
11 changes: 9 additions & 2 deletions src/platform/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,16 @@ mod os {
pub use super::macos::*;
}

#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android", target_os = "ios"))]
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
mod windows;
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
mod os {
pub use super::windows::*;
}

#[cfg(any(feature = "force-inprocess", target_os = "android", target_os = "ios"))]
mod inprocess;
#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android", target_os = "ios"))]
#[cfg(any(feature = "force-inprocess", target_os = "android", target_os = "ios"))]
mod os {
pub use super::inprocess::*;
}
Expand Down
151 changes: 147 additions & 4 deletions src/platform/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use std::thread;

#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))]
use libc;
use crate::platform::{OsIpcSender, OsIpcOneShotServer};
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android", target_os = "ios")))]
use libc::{kill, SIGSTOP, SIGCONT};
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android", target_os = "ios")))]
use crate::test::{fork, Wait};

// Helper to get a channel_name argument passed in; used for the
// cross-process spawn server tests.
#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))]
use crate::test::{get_channel_name_arg, spawn_server};

#[test]
fn simple() {
let (tx, rx) = platform::channel().unwrap();
Expand Down Expand Up @@ -209,7 +216,8 @@ fn with_n_fds(n: usize, size: usize) {

// These tests only apply to platforms that need fragmentation.
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
target_os = "freebsd")))]
target_os = "freebsd",
target_os = "windows")))]
mod fragment_tests {
use crate::platform;
use super::with_n_fds;
Expand Down Expand Up @@ -656,9 +664,32 @@ fn server_connect_first() {
(data, vec![], vec![]));
}

#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))]
#[test]
fn cross_process_spawn() {
let data: &[u8] = b"1234567";

let channel_name = get_channel_name_arg("server");
if let Some(channel_name) = channel_name {
let tx = OsIpcSender::connect(channel_name).unwrap();
tx.send(data, vec![], vec![]).unwrap();

unsafe { libc::exit(0); }
}

let (server, name) = OsIpcOneShotServer::new().unwrap();
let mut child_pid = spawn_server("cross_process_spawn", &[("server", &*name)]);

let (_, received_data, received_channels, received_shared_memory_regions) =
server.accept().unwrap();
child_pid.wait().expect("failed to wait on child");
assert_eq!((&received_data[..], received_channels, received_shared_memory_regions),
(data, vec![], vec![]));
}

#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android", target_os = "ios")))]
#[test]
fn cross_process() {
fn cross_process_fork() {
let (server, name) = OsIpcOneShotServer::new().unwrap();
let data: &[u8] = b"1234567";

Expand All @@ -674,9 +705,42 @@ fn cross_process() {
(data, vec![], vec![]));
}

#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))]
#[test]
fn cross_process_sender_transfer_spawn() {
let channel_name = get_channel_name_arg("server");
if let Some(channel_name) = channel_name {
let super_tx = OsIpcSender::connect(channel_name).unwrap();
let (sub_tx, sub_rx) = platform::channel().unwrap();
let data: &[u8] = b"foo";
super_tx.send(data, vec![OsIpcChannel::Sender(sub_tx)], vec![]).unwrap();
sub_rx.recv().unwrap();
let data: &[u8] = b"bar";
super_tx.send(data, vec![], vec![]).unwrap();

unsafe { libc::exit(0); }
}

let (server, name) = OsIpcOneShotServer::new().unwrap();
let mut child_pid = spawn_server("cross_process_sender_transfer_spawn", &[("server", &*name)]);

let (super_rx, _, mut received_channels, _) = server.accept().unwrap();
assert_eq!(received_channels.len(), 1);
let sub_tx = received_channels[0].to_sender();
let data: &[u8] = b"baz";
sub_tx.send(data, vec![], vec![]).unwrap();

let data: &[u8] = b"bar";
let (received_data, received_channels, received_shared_memory_regions) =
super_rx.recv().unwrap();
child_pid.wait().expect("failed to wait on child");
assert_eq!((&received_data[..], received_channels, received_shared_memory_regions),
(data, vec![], vec![]));
}

#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android", target_os = "ios")))]
#[test]
fn cross_process_sender_transfer() {
fn cross_process_sender_transfer_fork() {
let (server, name) = OsIpcOneShotServer::new().unwrap();

let child_pid = unsafe { fork(|| {
Expand All @@ -691,7 +755,7 @@ fn cross_process_sender_transfer() {

let (super_rx, _, mut received_channels, _) = server.accept().unwrap();
assert_eq!(received_channels.len(), 1);
let sub_tx = received_channels.pop().unwrap().to_sender();
let sub_tx = received_channels[0].to_sender();
let data: &[u8] = b"baz";
sub_tx.send(data, vec![], vec![]).unwrap();

Expand Down Expand Up @@ -981,3 +1045,82 @@ mod sync_test {
platform::OsIpcSender::test_not_sync();
}
}

// This test panics on Windows, because the other process will panic
// when it detects that it receives handles that are intended for another
// process. It's marked as ignore/known-fail on Windows for this reason.
//
// TODO -- this fails on OSX as well with a MACH_SEND_INVALID_RIGHT!
// Needs investigation. It may be a similar underlying issue, just done by
// the kernel instead of explicitly (ports in a message that's already
// buffered are intended for only one process).
#[cfg(not(any(feature = "force-inprocess", target_os = "android", target_os = "ios")))]
#[cfg_attr(any(target_os = "windows", target_os = "macos"), ignore)]
#[test]
fn cross_process_two_step_transfer_spawn() {
let cookie: &[u8] = b"cookie";

let channel_name = get_channel_name_arg("server");
if let Some(channel_name) = channel_name {
// connect by name to our other process
let super_tx = OsIpcSender::connect(channel_name).unwrap();

// create a channel for real communication between the two processes
let (sub_tx, sub_rx) = platform::channel().unwrap();

// send the other process the tx side, so it can send us the channels
super_tx.send(&[], vec![OsIpcChannel::Sender(sub_tx)], vec![]).unwrap();

// get two_rx from the other process
let (_, mut received_channels, _) = sub_rx.recv().unwrap();
assert_eq!(received_channels.len(), 1);
let two_rx = received_channels[0].to_receiver();

// get one_rx from two_rx's buffer
let (_, mut received_channels, _) = two_rx.recv().unwrap();
assert_eq!(received_channels.len(), 1);
let one_rx = received_channels[0].to_receiver();

// get a cookie from one_rx
let (data, _, _) = one_rx.recv().unwrap();
assert_eq!(&data[..], cookie);

// finally, send a cookie back
super_tx.send(&data, vec![], vec![]).unwrap();

// terminate
unsafe { libc::exit(0); }
}

// create channel 1
let (one_tx, one_rx) = platform::channel().unwrap();
// put data in channel 1's pipe
one_tx.send(cookie, vec![], vec![]).unwrap();

// create channel 2
let (two_tx, two_rx) = platform::channel().unwrap();
// put channel 1's rx end in channel 2's pipe
two_tx.send(&[], vec![OsIpcChannel::Receiver(one_rx)], vec![]).unwrap();

// create a one-shot server, and spawn another process
let (server, name) = OsIpcOneShotServer::new().unwrap();
let mut child_pid = spawn_server("cross_process_two_step_transfer_spawn",
&[("server", &*name)]);

// The other process will have sent us a transmit channel in received channels
let (super_rx, _, mut received_channels, _) = server.accept().unwrap();
assert_eq!(received_channels.len(), 1);
let sub_tx = received_channels[0].to_sender();

// Send the outer payload channel, so the server can use it to
// retrive the inner payload and the cookie
sub_tx.send(&[], vec![OsIpcChannel::Receiver(two_rx)], vec![]).unwrap();

// Then we wait for the cookie to make its way back to us
let (received_data, received_channels, received_shared_memory_regions) =
super_rx.recv().unwrap();
let child_exit_code = child_pid.wait().expect("failed to wait on child");
assert!(child_exit_code.success());
assert_eq!((&received_data[..], received_channels, received_shared_memory_regions),
(cookie, vec![], vec![]));
}
Loading