Skip to content

Conversation

@juan518munoz
Copy link
Contributor

We are currently not handling cases were a GenServer init fails, but has instanced tasks like timers or listeners, this is due to how we handle the run function:

    fn run(
        &mut self,
        handle: &GenServerHandle<Self>,
        rx: &mut mpsc::Receiver<GenServerInMsg<Self>>,
        state: Self::State,
    ) -> impl Future<Output = Result<(), GenServerError>> + Send {
        async {
            match self.init(handle, state).await {
                Ok(new_state) => {
                    self.main_loop(handle, rx, new_state).await?; // <- cancel & teardown are called inside
                    Ok(())
                }
                Err(err) => {
                    tracing::error!("Initialization failed: {err:?}");
                    Err(GenServerError::Initialization) // <- we are returning an error, without previously stopping tasks created!
                }
            }
        }
    }

A simple example where this would happen:

    struct FailingOnInitTask;

    impl GenServer for FailingOnInitTask {
        type CallMsg = ();
        type CastMsg = ();
        type OutMsg = ();
        type State = ();
        type Error = ();

        fn new() -> Self {
            Self
        }

        async fn init(
            &mut self,
            handle: &GenServerHandle<Self>,
            _state: Self::State,
        ) -> Result<Self::State, Self::Error> {
            let (_, rx) = spawned_rt::tasks::mpsc::channel::<Result<u8, ()>>();
            let stream = ReceiverStream::new(rx);
            spawn_listener(handle.clone(), |_| (), stream); // <- this listener would be left hanging
            Err(())
        }
    }

    #[test]
    pub fn test_failing_on_init() {
        let runtime = rt::Runtime::new().unwrap();
        runtime.block_on(async move {
            let mut fails_on_init = FailingOnInitTask::start(());
            fails_on_init.call(()).await.unwrap();
        });
    }

@juan518munoz juan518munoz marked this pull request as ready for review July 16, 2025 21:33
@juan518munoz juan518munoz merged commit ac4122c into main Jul 18, 2025
3 checks passed
@juan518munoz juan518munoz deleted the teardown_on_init_failure branch July 18, 2025 19:45
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

Successfully merging this pull request may close these issues.

4 participants