Repository: actix/actix (language: rust)

Issue:
SyncActor started from another SyncActor does not get messages
I am not sure whether it is a bug or I do not understand it correctly, but if I run a SyncActor from another SyncActor, the second one does not get messages. The minimum example is below: the SyncActor2 never gets the message (Msg2).

```rust
use actix::prelude::*;

struct SyncActor2;

impl Actor for SyncActor2 {
    type Context = SyncContext<Self>;
}

struct SyncActor1(Addr<SyncActor2>);

impl Actor for SyncActor1 {
    type Context = SyncContext<Self>;
}

impl SyncActor1 {
    fn run() -> SyncActor1 {
        SyncActor1(SyncArbiter::start(1, || SyncActor2))
    }
}

struct Msg1;

impl Message for Msg1 {
    type Result = ();
}

struct Msg2;

impl Message for Msg2 {
    type Result = ();
}

impl Handler<Msg1> for SyncActor1 {
    type Result = ();
    
    fn handle(&mut self, _: Msg1, _: &mut Self::Context) -> Self::Result {
        self.0.do_send(Msg2);
        println!("SyncActor1 got the message");
    }
}

impl Handler<Msg2> for SyncActor2 {
    type Result = ();
    
    fn handle(&mut self, _: Msg2, _: &mut Self::Context) -> Self::Result {
        println!("SyncActor2 got the message either");
    }
}

#[actix_rt::main]
async fn main() {
    let addr = SyncArbiter::start(1, || SyncActor1::run());
    addr.send(Msg1).await.unwrap();
    tokio::signal::ctrl_c().await.unwrap();
    println!("Ctrl-C received, shutting down");
    System::current().stop();
}
```


Discussion / hints:
This is a work around. The problem is sync actor would need to spawn on `actix_rt` for async message handling and you can't call `actix_rt::spawn` and spawn a future in sync context. Like the slightly modifed handle method show. 

```rust
use actix::prelude::*;
use std::sync::{Arc, Mutex};

struct SyncActor2;

impl Actor for SyncActor2 {
    type Context = SyncContext<Self>;
}

struct SyncActor1(Addr<SyncActor2>);

impl Actor for SyncActor1 {
    type Context = SyncContext<Self>;
}

impl SyncActor1 {
    fn run() -> SyncActor1 {
        let (tx, rx) = std::sync::mpsc::channel();
        let tx = Arc::new(Mutex::new(tx));
        System::current().arbiter().exec_fn({
            let tx = tx.clone();
            move || {
                let addr = SyncArbiter::start(1, || SyncActor2);
                tx.lock().unwrap().send(addr).unwrap();
            }
        });

        SyncActor1(rx.recv().unwrap())
    }
}

struct Msg1;

impl Message for Msg1 {
    type Result = ();
}

struct Msg2;

impl Message for Msg2 {
    type Result = ();
}

impl Handler<Msg1> for SyncActor1 {
    type Result = ();

    fn handle(&mut self, _: Msg1, _: &mut Self::Context) -> Self::Result {
        self.0.do_send(Msg2);

        actix_rt::spawn(async { println!("this would do nothing and not printed") });
        System::current().arbiter().send(Box::pin(async { println!("this would run") }));

        println!("SyncActor1 got the message");
    }
}

impl Handler<Msg2> for SyncActor2 {
    type Result = ();

    fn handle(&mut self, _: Msg2, _: &mut Self::Context) -> Self::Result {
        println!("SyncActor2 got the message either");
    }
}

#[actix_rt::main]
async fn main() {
    let addr = SyncArbiter::start(1, || SyncActor1::run());
    addr.send(Msg1).await.unwrap();
    tokio::signal::ctrl_c().await.unwrap();
    println!("Ctrl-C received, shutting down");
    System::current().stop();
}
```
We can spawn [this future](https://github.com/actix/actix/blob/2168eec23f22d0bd83fc857acb016bfc24d68fbe/src/sync.rs#L134) using arbiter method but I have no idea if it would work and/or have side effect.


Fix patch:
diff --git a/CHANGES.md b/CHANGES.md
index 60a23a472..c8e4af8a9 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -10,11 +10,13 @@
 * The `where` clause on `Response::fut()` was relaxed to no longer require `T: Unpin`, allowing a
   `Response` to be created with an `async` block [#421]
 * Allow creating `WeakRecipient` from `WeakAddr`, similiar to `Recipient` from `Addr`. [#432]
+* Send `SyncArbiter` to current `System`'s `Arbiter` and run it as future there. Enabling nested `SyncArbiter`s [#439]  
 
 [#421]: https://github.com/actix/actix/pull/421
 [#424]: https://github.com/actix/actix/pull/424
 [#427]: https://github.com/actix/actix/pull/427
 [#432]: https://github.com/actix/actix/pull/432
+[#439]: https://github.com/actix/actix/pull/439
 
 
 ## 0.10.0 - 2020-09-10
diff --git a/actix-derive/src/message.rs b/actix-derive/src/message.rs
index 62e7808e4..1f1bfae78 100644
--- a/actix-derive/src/message.rs
+++ b/actix-derive/src/message.rs
@@ -69,10 +69,10 @@ fn get_attribute_type_multiple(
             .map(|m| meta_item_to_ty(m).ok())
             .collect())
     } else {
-        return Err(syn::Error::new_spanned(
+        Err(syn::Error::new_spanned(
             attr,
             format!("The correct syntax is #[{}(type, type, ...)]", name),
-        ));
+        ))
     }
 }
 
diff --git a/src/sync.rs b/src/sync.rs
index 8462c07ea..5723d34aa 100644
--- a/src/sync.rs
+++ b/src/sync.rs
@@ -131,10 +131,10 @@ where
             });
         }
 
-        actix_rt::spawn(Self {
+        System::current().arbiter().send(Box::pin(Self {
             queue: Some(sender),
             msgs: rx,
-        });
+        }));
 
         Addr::new(tx)
     }
@@ -371,3 +371,59 @@ where
         }
     }
 }
+
+#[cfg(test)]
+mod tests {
+    use futures_channel::oneshot;
+
+    use crate::prelude::*;
+
+    struct SyncActor2;
+
+    impl Actor for SyncActor2 {
+        type Context = SyncContext<Self>;
+    }
+
+    struct SyncActor1(Addr<SyncActor2>);
+
+    impl Actor for SyncActor1 {
+        type Context = SyncContext<Self>;
+    }
+
+    impl SyncActor1 {
+        fn run() -> SyncActor1 {
+            SyncActor1(SyncArbiter::start(1, || SyncActor2))
+        }
+    }
+
+    struct Msg(oneshot::Sender<u8>);
+
+    impl Message for Msg {
+        type Result = ();
+    }
+
+    impl Handler<Msg> for SyncActor1 {
+        type Result = ();
+
+        fn handle(&mut self, msg: Msg, _: &mut Self::Context) -> Self::Result {
+            self.0.do_send(msg);
+        }
+    }
+
+    impl Handler<Msg> for SyncActor2 {
+        type Result = ();
+
+        fn handle(&mut self, msg: Msg, _: &mut Self::Context) -> Self::Result {
+            msg.0.send(233u8).unwrap();
+        }
+    }
+
+    #[actix_rt::test]
+    async fn nested_sync_arbiters() {
+        let addr = SyncArbiter::start(1, SyncActor1::run);
+        let (tx, rx) = oneshot::channel();
+        addr.send(Msg(tx)).await.unwrap();
+        assert_eq!(233u8, rx.await.unwrap());
+        System::current().stop();
+    }
+}


Test patch: