6

I have a process that I'm trying to send input to on OS X. I'm using Emacs' builtin functions for doing this: process-send-string and process-send-region. However, it seems that there are issues when doing this on OS X. Specifically, it seems that I cannot send a process more than 1 KiB of data. To demonstrate what I mean, here's an example.

I started an Elisp REPL with M-x ielm and ran the following command:

ELISP> (start-process "cat" "*cat*" "cat")
#<process cat>

Then I ran this (no reason I'm using f; it's just a letter I thought of):

ELISP> (process-send-string (get-process "cat") "fff\n")

And I got what I expected in the *cat* buffer:

fff

Now, what if I send this:

(process-send-string (get-process "cat") "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff\n")

That is a string of 1,024 f characters (which is 1 KiB), followed by a newline so that cat knows that's the end of the input line. That is a grand total of 1,025 bytes which is just over 1 KiB. When I run the above command, all I get in the *cat* buffer is:

^G

It is highlighted so I know that it's a control character. Specifically, this is the ASCII BEL which is number 7. I guess this means that Emacs is getting an error in its write call to cat. The cat process is still alive, though.

According to errno.h, 7 is the error number for the POSIX E2BIG error. E2BIG is described like so in man 2 intro:

7 E2BIG Arg list too long.  The number of bytes used for the argument
and environment list of the new process exceeded the limit NCARGS
(specified in <sys/param.h>).

However, NCARGS is defined as ARG_MAX in param.h. ARG_MAX is defined as 256 * 1024 in syslimits.h, which is 256 KiB. So it seems that I shouldn't be having this problem since my input size is well within the bounds. However, I notice the following settings which are also defined in the system headers:

syslimits.h:81:#define  MAX_CANON        1024   /* max bytes in term canon input line */
syslimits.h:82:#define  MAX_INPUT        1024   /* max bytes in terminal input */
...
syslimits.h:91:#define  PATH_MAX         1024   /* max bytes in pathname */
...
dirent.h:100:#define __DARWIN_MAXPATHLEN    1024
...
_types/_fd_def.h:42:#define __DARWIN_FD_SETSIZE 1024

All of these constants are set to 1024. I wonder if one of them is causing this errant behavior with cat described above. However, this doesn't happen in the terminal. It seems to be specific to Emacs.

Also, as a sanity check, I tested the exact same code in Emacs on Linux and found that everything behaves as expected. I can send well over 1 KiB to a cat process on Linux without a hitch. So is this an Emacs bug or an OS X bug? And more importantly, how can I fix it?

  • Not sure how to fix it, but you can circumvent it by creating your process with process-connection-type bound to nil so it doesn't use a tty but a pipe. – Stefan Mar 23 '18 at 13:33
  • @Stefan Thanks, that fixes the problem and clears things up. I wasn't sure whether I was dealing with a pty or a pipe, but that makes much more sense now. It makes a lot more sense that the ^G came from the pty complaining. If you write your comment as an answer, I'll accept it. – GDP2 Mar 23 '18 at 19:34
2

Not sure how to fix it (I really mean it: I've tried to fix this bug in the past, but my POSIX-fu is not strong enough), but you can circumvent it by creating your process with process-connection-type bound to nil so it doesn't use a tty but a pipe.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.