Erlang ports and thread safety

2019-07-19 14:58发布

问题:

I'm looking to call a C function from an Erlang process via an Erlang port, as described here:

http://www.erlang.org/doc/tutorial/c_port.html

In production I will need multiple Erlang processes calling the C function in parallel, each with a different set of arguments.

My question is, will this be thread safe at the C function level ?

The docs talk about the controlling Erlang process creating a 'connected process', which it sounds as if is responsible for creating an isolated instance of the 'external program' (C function).

So it sounds like it's thread safe at the C level but I'd like to be 100% sure.

TIA

回答1:

It may depend on your implementation, but with Ports, the answer is almost definitely "yes" for the reason you mention. If you were using a NIF and using shared memory inside of the NIF, you would have some concern for thread safety.

With ports, however, the "controlling process" acts as a serialization (as in arranged in a series) layer, meaning requests are handled one after the other and not all at once. Moreover, I believe (but do not know for certain) that the communication protocol ports use also requires this serial execution.



回答2:

A port is a program that communicates to the Erlang side using standard input output. Whether you need thread safety or not depends on the communication protocol you implement.

If you think in terms of a port being an erlang process (which for the erlang side is the abstraction your erlang code sees) you could implement a protocol whether for each request you send to it, it will block until it sends back a response, or that you could send several requests in parallel and get responses for all of them asynchronously.

Going the the C side, the implementation of the former case would be a simple loop doing

  1. read command from stdin
  2. process that command
  3. write result to stdout
  4. go to 1

The concurrency is handled in the erlang side as all incoming commands will pile up in the port inbox while the port is processing one at a time.

For the latter, you would need a mechanism to handle input messages git remote add origin git@bitbucket.org:samuelrivas/dfberl.git asynchronously, I'll use threads here for simplicity:

The main loop:

  1. read command from stdin
  2. spawn a thread to process it
  3. go to 1

The thread loop:

  1. process command
  2. write result to stdout

Note that threads will need some kind of locking when writing to stdout, I usually implement that part as yet another thread with an asynchronous queue where all the other threads publish results to.

In the second scenario you will have concurrency in the C side, so you need to care about thread safety. In the first one the C side doesn't handle any concurrency, so thread safety is not a concern there.