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

Process termination. #6

Open
yiyuanliu opened this issue Dec 23, 2021 · 1 comment
Open

Process termination. #6

yiyuanliu opened this issue Dec 23, 2021 · 1 comment

Comments

@yiyuanliu
Copy link
Contributor

yiyuanliu commented Dec 23, 2021

Processes may terminate in a number of ways, eg SIGTERM, SIGKILL, machine down. Currently, Madsim does not simulate processes termination very well.

Madsim provides kill function to terminate a host, but the semantic of the kill function is unclear.

See this code:

struct Foo(String);

impl Foo {
    fn new(name: &str) -> Foo {
        println!("foo::new in {}", name);
        Foo(name.to_owned())
    }
}

impl Drop for Foo {
    fn drop(&mut self) {
        println!("foo::drop in {}!", self.0);
    }
}

#[madsim::main]
async fn main() {
    let handle = madsim::Handle::current().create_host("127.0.0.1:10086").unwrap();
    handle.spawn(async move {
        let _foo = Foo::new("madsim");
        loop {
            madsim::time::sleep(std::time::Duration::from_secs(1)).await;
        }
    }).detach();

    madsim::time::sleep(std::time::Duration::from_secs(1)).await;
    madsim::Handle::current().kill("127.0.0.1:1".parse().unwrap());
    loop {
        madsim::time::sleep(std::time::Duration::from_secs(1)).await;
    }
}

Run this code with features sim enabled, we will find that foo::drop is called. This means that the kill function behaves more like SIGTERM than SIGKILL, and this function cannot simulate some unexpected events (machine failure, out of memory, etc.). We have no way to know that when all async tasks on that host will be dropped, so it's still hard to determine a suitable time to restart host.

If we replace sleep in spawned task with futures::future::pending::<()>().await. We will see that the drop function is not called, which looks like SIGKILL (but not same as SIGKILL).

It seems difficult to simulate SIGKILL or machine failure. If the drop function is not called, there may be resource leaks (memory, file locks, etc.)

Another problem is that drop function won't be called automatically after process termination. See this code:

struct Foo(String);

impl Foo {
    fn new(name: &str) -> Foo {
        println!("foo::new in {}", name);
        Foo(name.to_owned())
    }
}

impl Drop for Foo {
    fn drop(&mut self) {
        println!("foo::drop in {}!", self.0);
    }
}

#[madsim::main]
async fn main() {
    let handle = madsim::Handle::current().create_host("127.0.0.1:10086").unwrap();
    handle.spawn(async move {
        let _foo = Foo::new("madsim");
        loop {
            madsim::time::sleep(std::time::Duration::from_secs(1)).await;
        }
    }).detach();

    madsim::time::sleep(std::time::Duration::from_secs(1)).await;
}

Foo::drop won't be called run this code with feature sim or std. This makes it difficult for applications that use madsim to exit gracefully. It seems would be better to provide an async fn as an entry function when the host is created, like spawn_blocking in tokio. When this entry function exits, the host is considered finished. And provide a joinhandle to wait for the host to finish.

@wangrunji0408
Copy link
Member

Note: We should add a hook function on kill.

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