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 ?
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With