Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

atomically writing to a socket

I'm using process-send-string to send data to a socket connection, but I'm not satisfied with the effect of this function. Roughly, calling (process-send-string "foo") may end up in sending "bar" and then "foo", as explained below.

As pointed out by Emacs maintainers, the C code of process-send-string calls a function wait_reading_process_output (even before actually writing anything), which may run timers, which in turn may call process-send-string, and no ordering is enforced between such nested calls.

This makes it virtually impossible to implement an RPC protocol which is intended to be used by hooks called at uncontrolled times. So my question is, how could we achieve an atomic, "synchronized" writing primitive for this purpose ?

like image 924
Tiphaine Turpin Avatar asked Feb 20 '12 12:02

Tiphaine Turpin


People also ask

What is a socket write?

Behavior for sockets: The write() function writes data from a buffer on a socket with descriptor fs. The socket must be a connected socket. This call writes up to N bytes of data. Parameter Description fs. The file or socket descriptor.

Is socket send atomic?

For TCP sockets, if the value you specify for the len parameter is less than or equal to the send buffer size of the socket, the send process will be atomic; that is, either all of the data will be sent or none of it will be sent. If all of the data is sent, the return code is set to the value of the len parameter.

What is a socket in Ubuntu?

DESCRIPTION. Socket creates an Internet domain TCP or a UNIX domain stream socket and connects it to stdin and stdout. The host argument can be an Internet number in dot-notation (like ``130.149. 28.10'') or a domain name.

What is socket programming in Unix?

A Unix Socket is used in a client-server application framework. A server is a process that performs some functions on request from a client. Most of the application-level protocols like FTP, SMTP, and POP3 make use of sockets to establish connection between client and server and then for exchanging data.


1 Answers

You could do something like:

(defun my-send-cmd (proc str)
  (if (process-get proc 'my-waiting)
      (process-put proc 'my-pending (append (process-get proc 'my-pending) (list str)))
    (process-put proc 'my-waiting t)
    (process-send-string proc str)))

then in the process-filter, when you get the answer to a command, check `my-pending' and if non-nil, take the first arg, send it to the process, otherwise set my-waiting back to nil. Of course, this assumes that every command will get an answer from the server, and that you can't stream the commands.

This said, the behavior you see should probably count as a bug, or at least as a misfeature, so please report it with M-x report-emacs-bug.

like image 116
Stefan Avatar answered Oct 05 '22 23:10

Stefan