inejge / ldap3

A pure-Rust LDAP library using the Tokio stack
Apache License 2.0
220 stars 38 forks source link

[0.7] Sync version can't be used in async code #50

Closed Geobert closed 4 years ago

Geobert commented 4 years ago

Hi,

I migrated an internal project to 0.7 and being hit by this error:

thread 'main' panicked at 'Cannot start a runtime from within a runtime. This happens because a function (like `block_on`) attempted to block the current thread while the thread is being used to drive asynchronous tasks.', C:\Users\geobe\.cargo\registry\src\github.com-1ecc6299db9ec823\tokio-0.2.18\src\runtime\enter.rs:19:5

I'm using synchronous API but I can see the the synchronous implementation just block_on async code.

I don't know if this is intended and I'll switch to Async API but I wanted to signal this as a difference from 0.6 branch :)

Regards,

inejge commented 4 years ago

Huh, it was never intended to be used in this way. I suppose that with 0.6 it "worked" because tokio-core requires an explicit runtime handle for all operations. If the library had ever been ported to tokio-0.1, you'd have the same problem there.

So yes, switch to async throughout.

Geobert commented 4 years ago

It ended that I can't use async version, because it's in an trait impl from oxide-auth and it's sync. I'll use spawn_blocking to use sync version of ldap3. A pity, but it will work :)

EDIT: more details https://users.rust-lang.org/t/calling-async-while-implementing-sync-trait/43388

inejge commented 4 years ago

It should be possible to a) spin up an OS thread with its own Tokio runtime and one or more LDAP connections, b) make a synchronous bridge that will block in other threads and forward requests to the LDAP runtime. I don't yet see it as something that would be included in ldap3 proper, it's a bit specialized.

Do you have a repo/gist which could reproduce your problem config?

Geobert commented 4 years ago

Unfortunately it's closed source, but I can craft an example to demonstrate my issue yes:

example.zip

Geobert commented 4 years ago

I have a workaround for now (see the Rust forum thread above), but I think the simpler would be waiting for async oxide-auth (which is WIP)

inejge commented 4 years ago

Ah, from the URLO thread and the code I finally saw what you meant to do. The solution, spawn_blocking(), is not a workaround, but an architectural necessity: you don't want to call blocking operations directly in an async context, and the inverse doesn't work without a runtime. Of course, once every support library is async, you can use it exclusively.