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

Panic on large data transfer #277

Open
Geens opened this issue Aug 12, 2021 · 1 comment
Open

Panic on large data transfer #277

Geens opened this issue Aug 12, 2021 · 1 comment

Comments

@Geens
Copy link

Geens commented Aug 12, 2021

I get this strange panic when sending large messages to a child process. I was able to recreate the problem in this minimal example. The program runs correctly for smaller payload sizes, e.g. 60000.

Tested on:

  • OS: Windows 10
  • Rust: stable-x86_64-pc-windows-msvc unchanged - rustc 1.52.1 (9bc8c42bb 2021-05-09)
  • ipc_channel: v0.15.0
thread 'main' panicked at 'Windows IPC channel received handles intended for pid 10012, but this is pid 872. This likely happened because a receiver was transferred while it had outstanding data that contained a channel or shared memory in its pipe. This isn't supported in the Windows implementation.', C:\Users\geens\.cargo\registry\src\github.com-1ecc6299db9ec823\ipc-channel-0.15.0\src\platform\windows\mod.rs:158:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\ipc_channel_test.exe` (exit code: 101)
use ipc_channel::ipc;

fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() == 2 {
        child(args[1].clone());
    } else {
        parent(args[0].clone());
    }
}

fn parent(executable: String) {
    let (server, server_name) = ipc::IpcOneShotServer::new().unwrap();
    let mut child = std::process::Command::new(executable)
        .arg(server_name)
        .stdout(std::process::Stdio::piped())
        .spawn()
        .unwrap();
    let (_, (tx, rx)): (_, (ipc::IpcSender<String>, ipc::IpcReceiver<String>)) = server.accept().unwrap();
    let payload = "a".repeat(70000).to_owned();
    tx.send(payload.clone()).unwrap();
    let received = rx.recv().unwrap();
    assert_eq!(payload, received);
    child.wait().unwrap();
}

fn child(server_name: String) {
    let one_shot_sender = ipc::IpcSender::connect(server_name).unwrap();
    let (tx, rx_send) = ipc::channel().unwrap();
    let (tx_send, rx) = ipc::channel().unwrap();
    one_shot_sender.send((tx_send, rx_send)).unwrap();
    let payload: String = rx.recv().unwrap();
    tx.send(payload).unwrap();
}
@SamRodri
Copy link

SamRodri commented Sep 4, 2021

I encountered the same panic, it only happens if the receiver was created in a different process, so a workaround is to create the channel in the process the receiver will be used:

use ipc_channel::ipc;

fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() == 2 {
        child(args[1].clone());
    } else {
        parent(args[0].clone());
    }
}

fn parent(executable: String) {
    let (server, server_name) = ipc::IpcOneShotServer::new().unwrap();
    let mut child = std::process::Command::new(executable)
        .arg(server_name)
        .stdout(std::process::Stdio::piped())
        .spawn()
        .unwrap();

    let (_, (tx, workaround_tx)): (_, (ipc::IpcSender<String>, ipc::IpcSender<ipc::IpcSender<String>>)) = server.accept().unwrap();
    let (tx_send, rx) = ipc::channel().unwrap();
    workaround_tx.send(tx_send).unwrap();

    let payload = "a".repeat(70000);
    tx.send(payload.clone()).unwrap();
    let received = rx.recv().unwrap();
    assert_eq!(payload, received);
    child.wait().unwrap();
}

fn child(server_name: String) {
    let one_shot_sender = ipc::IpcSender::connect(server_name).unwrap();
    let (workaround_tx_send, workaround_rx) = ipc::channel().unwrap();

    let (tx_send, rx) = ipc::channel().unwrap();
    one_shot_sender.send((tx_send, workaround_tx_send)).unwrap();

    let tx: ipc::IpcSender<String>  = workaround_rx.recv().unwrap();

    let payload: String = rx.recv().unwrap();
    tx.send(payload).unwrap();
}

YaLTeR added a commit to YaLTeR/bxt-rs that referenced this issue May 31, 2022
YaLTeR added a commit to YaLTeR/bxt-rs that referenced this issue Jun 2, 2022
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

No branches or pull requests

2 participants