9

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?

Drew
  • 75,699
  • 9
  • 109
  • 225
GDP2
  • 1,340
  • 9
  • 25
  • 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

1 Answers1

3

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.

Stefan
  • 26,154
  • 3
  • 46
  • 84