Skip to content

Commit 859eed1

Browse files
vvukantrik
authored andcommitted
Implement ipc-channel on Windows
This implementation uses named pipes on Windows, with auto-generated uuid names. It takes advantage of DuplicateHandle to clone handles to target processes when sending handles cross-process. Shared memory is implemented using anonymous file mappings. select() and friends are implemented using IO Completion Ports.
1 parent 92ae015 commit 859eed1

File tree

6 files changed

+1535
-17
lines changed

6 files changed

+1535
-17
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ repository = "https://github.com/servo/ipc-channel"
1010
force-inprocess = []
1111
memfd = ["syscall"]
1212
unstable = []
13+
win32-trace = []
1314

1415
[dependencies]
1516
bincode = "1.0.0-alpha2"
@@ -27,3 +28,7 @@ syscall = { version = "0.2.1", optional = true }
2728

2829
[dev-dependencies]
2930
crossbeam = "0.2"
31+
32+
[target.'cfg(target_os = "windows")'.dependencies]
33+
winapi = "0.2"
34+
kernel32-sys = "0.2"

src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// option. This file may not be copied, modified, or distributed
88
// except according to those terms.
99

10-
#![cfg_attr(any(feature = "force-inprocess", target_os = "windows", target_os = "android"),
10+
#![cfg_attr(any(feature = "force-inprocess", target_os = "android"),
1111
feature(mpsc_select))]
1212
#![cfg_attr(all(feature = "unstable", test), feature(specialization))]
1313

@@ -18,6 +18,7 @@ extern crate bincode;
1818
extern crate libc;
1919
extern crate rand;
2020
extern crate serde;
21+
2122
#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
2223
extern crate uuid;
2324
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
@@ -32,6 +33,11 @@ extern crate fnv;
3233
extern crate syscall;
3334

3435

36+
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
37+
extern crate winapi;
38+
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
39+
extern crate kernel32;
40+
3541
pub mod ipc;
3642
pub mod platform;
3743
pub mod router;

src/platform/mod.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,16 @@ mod os {
4343
pub use super::macos::*;
4444
}
4545

46-
#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
46+
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
47+
mod windows;
48+
#[cfg(all(not(feature = "force-inprocess"), target_os = "windows"))]
49+
mod os {
50+
pub use super::windows::*;
51+
}
52+
53+
#[cfg(any(feature = "force-inprocess", target_os = "android"))]
4754
mod inprocess;
48-
#[cfg(any(feature = "force-inprocess", target_os = "windows", target_os = "android"))]
55+
#[cfg(any(feature = "force-inprocess", target_os = "android"))]
4956
mod os {
5057
pub use super::inprocess::*;
5158
}

src/platform/test.rs

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
use platform::{self, OsIpcChannel, OsIpcReceiverSet};
1111
use platform::{OsIpcSharedMemory};
1212
use std::collections::HashMap;
13-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
13+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
1414
use std::process::{Command, Stdio};
1515
use std::sync::Arc;
1616
use std::time::{Duration, Instant};
1717
use std::thread;
18-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
18+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
1919
use std::env;
2020

21-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
21+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
2222
use libc;
2323
use platform::{OsIpcSender, OsIpcOneShotServer};
2424
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
@@ -215,7 +215,8 @@ fn with_n_fds(n: usize, size: usize) {
215215

216216
// These tests only apply to platforms that need fragmentation.
217217
#[cfg(all(not(feature = "force-inprocess"), any(target_os = "linux",
218-
target_os = "freebsd")))]
218+
target_os = "freebsd",
219+
target_os = "windows")))]
219220
mod fragment_tests {
220221
use platform;
221222
use super::with_n_fds;
@@ -666,7 +667,7 @@ fn server_connect_first() {
666667
// Note! This test is actually used by the cross_process_spawn() test
667668
// below as a second process. Running it by itself is meaningless, but
668669
// passes.
669-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
670+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
670671
#[test]
671672
#[ignore]
672673
fn cross_process_server()
@@ -682,7 +683,7 @@ fn cross_process_server()
682683
unsafe { libc::exit(0); }
683684
}
684685

685-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
686+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
686687
#[test]
687688
fn cross_process_spawn() {
688689
let (server, name) = OsIpcOneShotServer::new().unwrap();
@@ -726,7 +727,7 @@ fn cross_process_fork() {
726727
// Note! This test is actually used by the cross_process_sender_transfer_spawn() test
727728
// below as a second process. Running it by itself is meaningless, but
728729
// passes.
729-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
730+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
730731
#[test]
731732
#[ignore]
732733
fn cross_process_sender_transfer_server()
@@ -746,7 +747,7 @@ fn cross_process_sender_transfer_server()
746747
unsafe { libc::exit(0); }
747748
}
748749

749-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
750+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
750751
#[test]
751752
fn cross_process_sender_transfer_spawn() {
752753
let (server, name) = OsIpcOneShotServer::new().unwrap();
@@ -972,7 +973,7 @@ mod sync_test {
972973
// Note! This test is actually used by the
973974
// cross_process_two_step_transfer_spawn() test below. Running it by
974975
// itself is meaningless, but it passes if run this way.
975-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
976+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
976977
#[test]
977978
#[ignore]
978979
fn cross_process_two_step_transfer_server()
@@ -1013,10 +1014,16 @@ fn cross_process_two_step_transfer_server()
10131014
unsafe { libc::exit(0); }
10141015
}
10151016

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

0 commit comments

Comments
 (0)