NOP0 / rustmatic

PLC programming in Rust!
Apache License 2.0
35 stars 2 forks source link

WIP: Proof of concept crate for running programs compiled to WASM #27

Closed Michael-F-Bryan closed 4 years ago

Michael-F-Bryan commented 4 years ago

(see also Michael-F-Bryan/adventures.michaelfbryan.com#2)

NOP0 commented 4 years ago

Seriously excited about this PR! Started reading your blog post on this. :+1:

NOP0 commented 4 years ago

@Michael-F-Bryan : Stupid question: Why is it so important to clear the pointer to the wasmer ctx between each poll? If the Program panics, don't we have to setup again using with_env anyways, and then the pointer will be valid? Granted, it's getting late here. Logging out 🙂

Michael-F-Bryan commented 4 years ago

If we don't clear the data pointer before the with_env helper finishes, the data pointer will be non-null and dangling. All host functions assume that a non-null data pointer is valid, so if it's dangling we're gonna have a bad time.

This situation should be impossible to encounter. My concern is you may (somehow, possibly via callbacks or invoking functions manually) do something which will call a host function without first having gone through that with_env helper and setting up the data pointer correctly. I'd just like to make doubly sure it can't happen.

NOP0 commented 4 years ago

Should I be getting "Polling" when I run the example at this stage?

Michael-F-Bryan commented 4 years ago

Yep. The example-program.rs just logs "Polling" every time poll() gets called, and the basic runtime will call poll() in a loop as fast as it can.

Michael-F-Bryan commented 4 years ago

I've merged the original blog post (Michael-F-Bryan/adventures.michaelfbryan.com#2) and think we've done enough to unblock other parts of the project.

@NOP0, can you help review this? The article literally contains the thoughts I had while I was working on this PR, so that may be a useful (if somewhat long and convoluted) explanation of how things were implemented and where I'm trying to go with it.

NOP0 commented 4 years ago

@NOP0, can you help review this? The article literally contains the thoughts I had while I was working on this PR, so that may be a useful (if somewhat long and convoluted) explanation of how things were implemented and where I'm trying to go with it.

@Michael-F-Bryan For sure! It's non-trivial stuff for me, so I'll probably need a few days go through this properly if you don't mind. Get it running locally and so on. The final version of the blog post will come in handy. :+1:

NOP0 commented 4 years ago

Went through all of it, and tested locally. I think it's a really good base to build on. Nice that you already made some tooling to help us with. :+1: All I can say is good work, there's gotta be a lot of hours here, for sure. I would merge this :smile:

I'm still a little foggy on whether core::ProcessImage and root::runtime will be running "underneath" this wasm-runtime or side-by-side etc? Could you explain a little about that?

Michael-F-Bryan commented 4 years ago

I'm still a little foggy on whether core::ProcessImage and root::runtime will be running "underneath" this wasm-runtime or side-by-side etc? Could you explain a little about that?

I'm not 100% sure how it'll look either :rofl:

I think we'll create a struct (e.g. rustmatic_runtime::WasmProcess) which contains a rustmatic_wasm::Program and implements rustmatic_core::Process, deferring to the Program's poll() method. Then we'd register the WasmProcess as just another process to be executed by the Runtime.

Internally the Runtime contains a ProcessImage to help track IO state. When polling processes we'll use the rustmatic_core::System trait to give them access to certain parts of the runtime (IO, global variables, the time, etc.) via a well defined interface while making sure no rustmatic_core::Processes actually have access to the full Runtime.

It may feel a little boilerplate-y to have so many traits, but it's really beneficial when you want to allow different parts of the system to be rewritten/restructured without breaking the world. As a nice side-effect, mocking things out during testing becomes trivial and you won't need to spin up a heavy-weight runtime just to check a single poll() method.