Need help understanding memory allocations in this code

#1: yes, the closure captures its environment. Rebinding client after the call to Task.Supervisor.start_child won’t change the value the child process sees.

#2: the thing that’s returned from :gen_tcp.accept is usually a “port”; short short version it’s a way to name the thing that’s actually holding the OS socket. Calling controlling_process tells the port that it should send messages etc to the newly-started task instead of the process that originally called :gen_tcp.accept.

#3: there’s no state attached to the module KVServer, so asking whether there’s a second “copy” of it isn’t particularly meaningful. There’s some very tricky corner-cases around hot-code reloading that make calling serve(client) different from calling KVServer.serve(client) (even from inside a function defined in KVServer!) but most people will never encounter them.