Modifying an Running Application

I was listening to the Query Planning & Optimization (CMU Intro to Database Systems / Fall 2022) and they talked of compiling functions for incoming SQL queries and then running that compiled code. Is it possible in a running ghc application to run code that ghc just compiled?

3 Likes

Yes, although perhaps not easily currently. The plugins package used to make this easier. And if there is only limited context from the running program necessary, hint can be used (the problem with hint is that it will run things in a different Haskell runtime environment than that of your program, so you would need a way to serialize data to and from your code).

2 Likes

Hotswapping is hard because once your Haskell code is compiled, it no longer has any ties to its compiler.

I watched a talk by Simon Marlow describing how his team used hotswapping at Meta. The associated package is ghc-hotswap, but I have never used it.

Edit: there’s more in this blog post

5 Likes

If you were feeling really adventurous, you could do what old MUD servers (and maybe others?) used to do:

  1. Create a pipe(2). This will be how the old instance of the program sends its state to the new instance.
  2. fork(2) to get a copy of the current process. This is Control.Concurrent.forkOS. Beware if you’re doing any other multithreading while you do this!
  3. The parent process calls exec(3) to replace itself with the new version, including telling it the FD of the pipe to read from.
  4. The child process writes its state down the pipe and then exits. (The reason the parent calls exec(3) and the child writes the state is to preserve the PID of the long-running process.)
  5. The parent process reads and deserialises its state from the pipe, then calls wait(2) or waitpid(2) to clean up the terminated child process.

This is not especially easy, because you need to turn file descriptors back into Handles, make sure you’ve got all your Haskell-level buffers in order, etc. But it is possible in principle.

4 Likes