News for hackers. Stuff that matters.
Re:My favorite Erlang program (2013) by refactorworks on Wednesday September 06, 2023 @11:41PM (#37414500)
universal_server() -> receive {become, F} -> F() end.

Honestly I don't fully appreciate the power of this universal server. Can anyone help?

Re:My favorite Erlang program (2013) by brokencode on Wednesday September 06, 2023 @11:52PM (#37414556)
Normally you need to know ahead of time what your server is going to be used for and write the code in advance.

But with Erlang, you can have a distributed network of Erlang servers where the server is a generic computing resource that can do anything the client wants.

The code actually comes from the client. No need to get your system administrators to install some binary on all the machines. You simply pass the function along and the remote machine calls it.

Re:My favorite Erlang program (2013) by refactorworks on Thursday September 07, 2023 @12:02AM (#37414618)
Thanks! I get it — no need to install binaries of specific servers.
Re:My favorite Erlang program (2013) by rramadass on Thursday September 07, 2023 @01:53AM (#37415212)
Re:My favorite Erlang program (2013) by nesarkvechnep on Thursday September 07, 2023 @02:57AM (#37415606)
Double check whether you think of the correct abstraction level. The BEAM is more like the JVM than Kubernetes.
Re:My favorite Erlang program (2013) by zbentley on Thursday September 07, 2023 @10:26AM (#37419368)
One of the most interesting characteristics of the BEAM, in my opinion, is that it's similar to both. As a memory-managed bytecode runtime it's similar to the JVM, and as a distributed process orchestrator+discovery and RPC system, it's similar to Kubernetes.

I often wonder what would have happened if the "BEAM renaissance" (driven largely by the birth of Elixir and associated tools) had happened a decade earlier, before Kubernetes became the de-facto standard for ad-hoc distributed computing in web software.

Re:My favorite Erlang program (2013) by zaphirplane on Thursday September 07, 2023 @03:42AM (#37415868)
A few people here are liking the idea, isn’t this the exact definition of arbitrary code execution (exploit)

It’s possible people are showing the capability of BEAM thou

Re:My favorite Erlang program (2013) by coldtea on Thursday September 07, 2023 @06:21AM (#37416908)
It's the definition of any distributed system (or even single server) where you can deploy code, whether it's Erlang or a kubernetes cluster you setup.

Is pushing new code for your server to run "arbitrary code execution"? I guess we can call it that. Is it an exploit?

Depends if the code comes from some random person on the internet from mechanisms that you don't intend for pushing new code to run (e.g. through a buffer overflow on your server or XSS), or if it comes from yourself through your official mechanisms.

Re:My favorite Erlang program (2013) by jerf on Thursday September 07, 2023 @09:59AM (#37419024)
"Arbitrary code execution", yes, "exploit", no. You need to be "inside" the BEAM cluster and a member of the BEAM cluster to do this. That is not something you hand off to end users, just as you do not normally hand end users direct access to your database socket or other such resources. In Raymond Chen's terminology [1], if you're sending Erlang terms to the BEAM cluster, you're already on the privileged side of the airtight hatchway.

[1]: https://devblogs.microsoft.com/oldnewthing/20060508-22/?p=31...

Re:My favorite Erlang program (2013) by brokencode on Thursday September 07, 2023 @10:07AM (#37419103)
Only if you allow untrusted clients to join to the cluster. To really make use of something like this, you’d have to control the clients rather than opening it up to anybody on the public internet.
Re:My favorite Erlang program (2013) by macintux on Wednesday September 06, 2023 @11:53PM (#37414560)
I may be answering the wrong question, but I’ll give it a shot.

Erlang’s architecture is unusual; both the virtual machine and the language are built around the idea of tiny processes operating concurrently, each process running in an infinite loop waiting for incoming messages to interpret.

This allows a process to become whatever code you send it. If you need a process to control a microwave, and then run some quantum computations, and then predict the winner of tomorrow’s football game, you just send it the code it needs for each operation and it happily does so.

Re:My favorite Erlang program (2013) by notRobot on Wednesday September 06, 2023 @11:58PM (#37414597)
Ah, so TL;DR is that each process evals the supplied code and returns the output to the caller?
Re:My favorite Erlang program (2013) by Jtsummers on Thursday September 07, 2023 @12:11AM (#37414674)
The universal server may or may not return anything. It just executes whatever is passed to it. In Erlang there are two ways of "calling" (in quotes for a reason). There's conventional function calling which is the regular synchronous style that we all know and love:

  f(10).
This will produce a result and return it to its caller. The other isn't really a call, it's "sending":

  Pid ! 10.
Some process id has been sent the value 10. It may be on this same node, it may be on another node, I don't have to care (sometimes I do though). This is asynchronous. Once a send is done the sending process will continue on (perhaps even terminating). At the other end of the send is a receive (hopefully, otherwise somebody's queue is getting filled up...):

  receive
    N -> ... % do something with this value
  end.
In the case of `universal_server` we don't know what it will become, it's just going to execute whatever 0-ary function is passed. That function may or may not include a "return" (sending a value back to the origin). It could also just terminate the universal server. Or it could temporarily convert the universal server into something else and then become a universal server again.
Re:My favorite Erlang program (2013) by macintux on Thursday September 07, 2023 @12:00AM (#37414610)
Slightly different in the low-level details, but conceptually accurate.
Re:My favorite Erlang program (2013) by Jtsummers on Wednesday September 06, 2023 @11:55PM (#37414575)
You execute that on any node in your system and send it a message `{become, fun some_function/0}`. Once it receives that conforming message (a tuple of two items, the atom `become` and a 0-ary function) and that node will stop being a "universal server" and become whatever process "some_function" describes.

And in his case he had access to some 9000 computers. If each was running at least one Erlang node and each node was running a universal server, then with a very simple program he could write a function, serialize the function, and distribute the function to his 9k+ running universal servers and turn them into 9k+ specialized servers.

Re:My favorite Erlang program (2013) by softirq on Wednesday September 06, 2023 @11:57PM (#37414584)
If you are familiar with Go, it's similar to a goroutine that waits for someone to send it an anonymous function to start executing. In Erlang, you solve problems by spawning lots of processes, and most processes are waiting to accept messages. One critical difference is that in Erlang, processes can run on remote machines, seamlessly. This process accepts a message which is a tuple containing the atom become, which is basically just an enum, and a function. Another process, such as the Erlang shell, can send this tuple message with the function to this process at any time so that it "becomes" that function.

What he is saying is that you can swap out the logic of this waiting loop with whatever protocol logic you want. His example was that he had a fleet of machines that were running this loop, and he sent all of them a function that implemented a gossip protocol. But he could easily send them all another message that turns them all into BitTorrent clients.

Joe was an absolute genius and an extremely kind person. I had the honor of meeting him once. Erlang is still one of the most beautiful technical creations I've ever encountered. It really does make you see concurrency in a whole new way.

Re:My favorite Erlang program (2013) by thakoppno on Thursday September 07, 2023 @12:40AM (#37414828)
> One critical difference is that in Erlang, processes can run on remote machines, seamlessly.

Is there a concise way to explain how Erlang achieves this property?

Re:My favorite Erlang program (2013) by querulous on Thursday September 07, 2023 @01:04AM (#37414952)
it's not as mysterious as it sounds. every data structure (including modules and anonymous functions) has a binary serialization and every erlang vm is also an rpc server that can receive arbitrary data -- including whole programs -- and execute them. your vm of course needs to know about the remote vms to do so but that's where the rudimentary clustering mechanism in erlang comes into play
Re:My favorite Erlang program (2013) by thomasfortes on Thursday September 07, 2023 @01:13AM (#37414991)
Also no shared memory in processes and they all communicate strictly through message passing, so running a piece of code in the local node, in another node in the same machine or in a node on the other side of the planet is a matter of telling which pid you want to send the message to, the BEAM will figure out how to send the message to the correct place in the cluster and your program will be none the wiser.
Re:My favorite Erlang program (2013) by rramadass on Thursday September 07, 2023 @01:44AM (#37415159)
You can find all the details about Erlang internals in The BEAM book : https://blog.stenmans.org/theBeamBook/
Re:My favorite Erlang program (2013) by coldtea on Thursday September 07, 2023 @06:11AM (#37416836)
It's basically a distributed RPC system. Your call is a message.
Re:My favorite Erlang program (2013) by tombert on Thursday September 07, 2023 @01:25AM (#37415052)
> Joe was an absolute genius and an extremely kind person. I had the honor of meeting him once.

Completely agree. Joe was always willing to reply to my emails and answer my questions in detail. He was an exceptionally talented explainer, and his messages were always interesting and entertaining, while also being informative.

I never met him in person but I will always treasure the correspondence I had with him.

Re:My favorite Erlang program (2013) by henrik_w on Thursday September 07, 2023 @02:50AM (#37415564)
On the subject of beauty, I really like this quote from Joe Armstrong:

“Make it work, then make it beautiful, then if you really, really have to, make it fast. 90 percent of the time, if you make it beautiful, it will already be fast. So really, just make it beautiful!”

Re:My favorite Erlang program (2013) by nojs on Thursday September 07, 2023 @05:09AM (#37416450)
I would be interested if you could elaborate on the advantages and disadvantages of Erlang/Elixir over Go. I have often heard Elixir processes likened to goroutines. Since the process model seems like the primary advantage of Erlang, why would one prefer Erlang/Elixir over Go?
Re:My favorite Erlang program (2013) by coldtea on Thursday September 07, 2023 @06:14AM (#37416859)
More dynamic, better management, dead easy to get distributed programs in multiple machines.
Re:My favorite Erlang program (2013) by ramchip on Thursday September 07, 2023 @07:13AM (#37417277)
The critical difference is that processes are isolated, they don't share resources like goroutines do. This makes it possible to separate the error handling from the business logic.

When you open a file, a socket, allocate memory, borrow a database connection from a pool, etc. you don't need to write try/catch/finally, or defer() statements, or logging, or any kind of error handling like that - if your code crashes, the VM will take care of the cleanup (because it knows what resources are owned by your process) and the supervisor above your process will log the problem and restart the process if necessary.

This makes Erlang applications much safer by default, and the business logic is clearer and simpler because it's not mixed with error recovery code (the "if err != nil" every other line that Go is famous for). The error kernel (the part of the app that must be carefully written to ensure reliability) can be kept really small[1].

This comes at a cost in performance, because data must generally be copied between processes, whereas goroutines can send pointers directly to each other. But if you can afford it, it's _very_ nice. Besides the error handling this also enables crazy observability (you can connect to a running app and inspect processes[2], kill them, send them messages, jump between nodes in a cluster, etc.), live code reload, and a bunch of nice things like that.

[Process isolation also enables clustering, where processes running on different machines can talk to each other as if they were in the same OS process. The copying means it doesn't matter if the other process is remote or local.]

[1] https://medium.com/@jlouis666/error-kernels-9ad991200abd

[2] https://github.com/zhongwencool/observer_cli#demo

Re:My favorite Erlang program (2013) by mietek on Thursday September 07, 2023 @07:59AM (#37417661)
Copying doesn't always have to happen. The Erlang VM is free to share blobs behind the scenes.
Re:My favorite Erlang program (2013) by ramchip on Thursday September 07, 2023 @08:11AM (#37417783)
Indeed, hence the "generally" :-)
Re:My favorite Erlang program (2013) by smashedtoatoms on Thursday September 07, 2023 @08:09AM (#37417763)
The clustering is what makes it feel so different, and what makes it such a compelling runtime for certain types of problems.

It's not an accident that large distributed chat programs or MQ systems are often written in erlang. From inside the code, writing a distributed system feels the same as working on one node.

With go, you can't do channels to a go process running on a different server without significantly changing the language. In erlang, you don't notice because that's just how it works.

Write an app that runs on two nodes and sends updates to all clients via websockets. In erlang, you just write it. In EVERY other language, you're loading a non-idiomatic library and probably running an MQ cluster or using an MQ service... probably written in erlang.

Re:My favorite Erlang program (2013) by jerf on Thursday September 07, 2023 @09:54AM (#37418950)
I wrote up a fairly detailed comparison of the concurrency models, as someone who has used both for years, a few months ago: https://news.ycombinator.com/item?id=34564228
Re:My favorite Erlang program (2013) by agundy on Wednesday September 06, 2023 @11:57PM (#37414588)
This universal server is a process listening for a message with a function and then it executes that function here the function is just a different infinite server turning a running process into something new. I think it shows off the power of erlang processes and the ability to pass functions to replace running processes with new behavior without changing pids.
Re:My favorite Erlang program (2013) by h0l0cube on Thursday September 07, 2023 @12:01AM (#37414613)
To explain further, the `receive` keyword is a bit like a switch statement (but actually a pattern matcher) for incoming messages.

Here they made a new server that takes an return process (From) and a number (N). The exclamation point sends the result back to the return process.

    factorial_server() ->
        receive
           {From, N} ->
               From ! factorial(N),
               factorial_server()
        end.

    factorial(0) -> 1;
    factorial(N) -> N * factorial(N-1).
This code then spawns the server, sends a message to that server to become a factorial server, then tells that server to send it back a message with the factorial of 50. It then specifies it's own message listener that takes whatever it receives and returns it.

    test() ->
        Pid = spawn(fun universal_server/0),
        Pid ! {become, fun factorial_server/0},
        Pid ! {self(), 50},
        receive
            X -> X
        end.
A couple of the major advantages of Erlang its distributed parallel nature, and also hot code update. Which happens in `Pid ! {become, fun factorial_server/0}` where it overides the receive loop of universal_server with that of the factorial_server. Though I think proper hot code update doesn't work like this
Re:My favorite Erlang program (2013) by coldtea on Thursday September 07, 2023 @06:20AM (#37416890)
And /0 is the local vm?
Re:My favorite Erlang program (2013) by chrisoverzero on Thursday September 07, 2023 @06:34AM (#37417007)
`/0` refers to the arity of the function.
Re:My favorite Erlang program (2013) by codemonkey-zeta on Thursday September 07, 2023 @07:23AM (#37417370)
It's the arity of the function. In Erlang there are no variadic functions, but functions with different arities can have the same name, so universal_server/0 takes no arguments, fib/1 takes 1 argument, fib/2 takes 2 arguments, the second arg may be the accumulator for a recursive Fibonacci, for example, and fib/1 may call fib/2 as an implementation detail.
Re:My favorite Erlang program (2013) by jay-barronville on Thursday September 07, 2023 @12:02AM (#37414621)
Basically, the idea is that it can become any type of server you’d like. The actual function to run the server is passed by the client and the Erlang process effectively morphs into that server after constructing it using the provided function. When you consider Erlang’s hot reloading abilities, this simple architecture becomes even more powerful. Another way to look at it is that the Erlang process is just compute waiting for work to do and the work is to run full-blown servers. Pretty neat.
Re:My favorite Erlang program (2013) by jay-barronville on Thursday September 07, 2023 @12:04AM (#37414627)
I was typing this answer on my phone and I didn’t realize several folks already responded. Move along, nothing to see here. Haha.
Re:My favorite Erlang program (2013) by xvilka on Thursday September 07, 2023 @12:04AM (#37414628)
Is the same trick possible with other BEAM languages? E.g. Elixir?
Re:My favorite Erlang program (2013) by qohen on Thursday September 07, 2023 @12:23AM (#37414741)
Yes. Here[0] is a gist showing it done in Elixir -- as you'll see, it looks very similar to the Erlang code:

[0] https://gist.github.com/mndvns/80b00cf67d418e8359fb5566b80ae...

Re:My favorite Erlang program (2013) by hmmokidk on Thursday September 07, 2023 @12:25AM (#37414749)
Yeah. I don’t see why not.
Re:My favorite Erlang program (2013) by ungamedplayer on Thursday September 07, 2023 @12:51AM (#37414890)
Here is an aggressive worm/virus that exploits this exact mechanism.

https://github.com/wmealing/Elixir-virus

Re:My favorite Erlang program (2013) by rramadass on Thursday September 07, 2023 @01:57AM (#37415238)
Yes; it is a property of the "Erlang Run Time System"(ERTS)/"VM"(BEAM) - https://news.ycombinator.com/item?id=37415159
Re:My favorite Erlang program (2013) by javajosh on Thursday September 07, 2023 @04:48AM (#37416314)
You can achieve the same goal, if not so elegantly, if you define a node process that processes HTTP POSTs by evaling the body of the request to replace the previous handling function. In practice you'd quickly want to post a function that behaves normally. However you could also define a function that does something "normal" but has a code path for continually redefining the function.

As exotic as this sounds, this is very similar to what web-browsers do with script src tags, especially from 3rd parties. The page is saying "Hey let me eval a function that can do whatever it wants in this context. I trust you!" Most webdevs don't consider this a threat vector!

Re:My favorite Erlang program (2013) by octacat on Thursday September 07, 2023 @05:39AM (#37416638)
It is a nice example, which would be rarely used in the real systems. Could be used for understanding how hot-code reloading could be implemented. Real usage could be if we have some big state and wanna apply some operations on it, we could send "{execute, F}" into the server and pass code (i.e. a simple reference) instead of data.