Skip to content

Commit 9f0304e

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 a18d54d commit 9f0304e

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();
@@ -727,7 +728,7 @@ fn cross_process_fork() {
727728
// Note! This test is actually used by the cross_process_sender_transfer_spawn() test
728729
// below as a second process. Running it by itself is meaningless, but
729730
// passes.
730-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
731+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
731732
#[test]
732733
#[ignore]
733734
fn cross_process_sender_transfer_server()
@@ -747,7 +748,7 @@ fn cross_process_sender_transfer_server()
747748
unsafe { libc::exit(0); }
748749
}
749750

750-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
751+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
751752
#[test]
752753
fn cross_process_sender_transfer_spawn() {
753754
let (server, name) = OsIpcOneShotServer::new().unwrap();
@@ -974,7 +975,7 @@ mod sync_test {
974975
// Note! This test is actually used by the
975976
// cross_process_two_step_transfer_spawn() test below. Running it by
976977
// itself is meaningless, but it passes if run this way.
977-
#[cfg(not(any(feature = "force-inprocess", target_os = "windows", target_os = "android")))]
978+
#[cfg(not(any(feature = "force-inprocess", target_os = "android")))]
978979
#[test]
979980
#[ignore]
980981
fn cross_process_two_step_transfer_server()
@@ -1016,10 +1017,16 @@ fn cross_process_two_step_transfer_server()
10161017
unsafe { libc::exit(0); }
10171018
}
10181019

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

0 commit comments

Comments
 (0)