Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Dynamically unloading/reloading DLLs to re-update code.

Cool if you can pull it of, but seems very house-of-cards. All you need is one bad reference floating around and boom.

I kinda wonder what this would look like in Rust. You could track all the lifetimes appropriately and make sure nothing got a handle into code that could be dynamically unloaded.

You'd keep all the native performance gains but without being nearly so brittle.



We included crash protection into RCC++: http://runtimecompiledcplusplus.blogspot.co.uk/2011/09/crash...

I use RCC++ daily as part of my development routine, and although you can introduce problems which mean you need to relaunch the program, the fact that you save having to do so most of the time is a big win for iteration.


Yeah, I'm all for fast iteration, was just musing aloud if there's some extra benefits to using Rust.

For instance your crash protection catches execution failures, but what about data failures? If you've got a write-past on an object nothing is going to be keeping you from destroying the rest of the world(unless all allocations in a hot-reload scenario are constrained to separate pages that you can protect?).

Seems like a lot if things you're trying to avoid by catching crashes are built-in to Rust.


The issues you mention exist in C++ without runtime compilation, so don't pose a particular blocker to using runtime compilation when you want fast iteration in C++. This is all intended for development environments, so 'destroying the world' simply means closing the application and restarting, which without RCC++ is something you have to do every time.

So there may be benefits to using Rust, but the issues you've posed are not ones I've found were my primary concerns when working on code which needs fast development iteration.


Hi, me and a few others in the Rust community kinda hashed out an plan of how you would do safe code un- and reloading Rust. Its nothing official, and has no implementation or official RFC/proposal yet, but the idea goes something like this:

- Rust as-is assumes program code/static memory is always valid/has the 'static lifetime. This assumption is implicit in the sense of function pointers, trait object vtables, static variables etc all having no lifetime bounds on something else than 'static, which means unloading their backing memory would cause unsafety.

- Thus, in order to make safe code unloading safe there would have to be a new, optional compile mode in which the compiler would treat "static" things like function pointers, trait objects, statics etc as non-'static, eg by giving them the new concrete lifetime "'crate". So if you have a "static FOO: T;" in a unloadable crate, you could only get a "&'crate T" to it, and you could only coerce to trait objects with a "+ 'crate" lifetime bound.

- 'crate would be similar to 'static in that it represents memory valid for the lifetime of the crate, but unlike 'static would not imply being always valid, and as such the borrow checker would prevent a bunch of operations for it like subtyping with any other lifetime, or usage with API's that want 'static bounds like thread spawning.

- Because 'crate is distinct from 'static, mixing unloadable and loadable code would be safe since the regular lifetime checking would ensure correct interaction between both. It means unloadable crates need to be explicitly written as such though.

- There are some major complications with generics and other compiler-generated glue code like vtables that are not fully hashed out yet: The issue there is that machine code corresponding to an upstream dependency gets compiled into the binary of the current crate, which means you would have code that typechecked with the assumptions of living in one binary be generated in another. Solutions here include banning generics and trait objects to types from extern crates, re-checking generics at instantiation location similar to C++ templates, or adding a new feature for instantiating generics outside the current crate, similar to "extern template" in C++.


Keep in mind that when you have a dll you are unloading instructions, not data.

Also C++ has unique_ptr that also tracks lifetimes, I don't think Rust would really give you anything you don't already have and I think you are overestimating the fragility. I've done hot reloading of .dll and it isn't really all that fragile. If you have the c runtime as a dynamic .dll the heap won't be tied to the .dll either.


uniqe_ptr does not "track lifetimes".

For example, this Rust program:

  fn main() {
       let r: &i32;

      {
          let b = Box::new(i32);
          r = &*b;
      }

      // r is dangling here, this would be bad:
      println!("{}", r);
  }
Is caught at compile time. Rust keeps track of the lifetime of both b and r, and knows that r will be dangling.

The C++ version:

  #include<iostream>
  #include<memory>

  using namespace std:

  int main() {
      int *r;

      {
          uniq_ptr<int> b(new int(5));
 
          r = &*b;
      }

      // r is dangling here
      cout << r << endl
  }
This compiles with no warnings under -Wall -Wextra with no warnings, and happily does whatever you ask with r, even though it's dangling.

Yes, this specific example is a bit contrived, but such is the way of examples. My point is just that C++'s smart pointers are a great thing, but that doesn't mean they do everything that Rust's do.


unique_ptr does not track lifetimes in any way. Nothing in C++ does.


Should be able to tie the lifetimes togethor with something like weak pointers/shared pointers but more task specific such that it blocks the unloading/reloading until all shared references are gone but the weak pointers can still connect to new versions. Shouldn't be brittle, but "shouldn't" may or may not be a four letter word.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: