bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#12440: 24.2; process-send-string only sends 4K for long strings


From: Lars Ingebrigtsen
Subject: bug#12440: 24.2; process-send-string only sends 4K for long strings
Date: Mon, 07 Oct 2019 16:53:24 +0200
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux)

Hendrik Tews <tews@os.inf.tu-dresden.de> writes:

> in Emacs 24.2, the following code
>
>   (let* ((process-connection-type t)
>          (process (start-process "cat" (current-buffer) "cat")))
>     (process-send-string process (format "%s\n" (make-string 6000 ?a))))
>
> inserts only 4095 characters in the current buffer. Setting
> process-connection-type to nil will insert all characters.

I can confirm that this bug is still present in Emacs 27.

It's odd that this doesn't cause more problems than it does in practice,
but I guess it's rare that we talk to processes this way.

The bug was apparently introduced by the patch below, but I have to
admit when reading it, I don't quite understand what's going on...

commit 2b0a91e78f83fb446cc38efb99399e83ad2cded3
Author: Stefan Monnier <monnier@iro.umontreal.ca>
Date:   Mon Apr 12 22:07:48 2010 -0400

    Try to solve the problem of spurious EOF chars in long lines of text
    sent to interactive subprocesses.
    * sysdep.c (child_setup_tty): Do not enable ICANON any more.
    (system_process_attributes): Remove unused var `ttotal'.
    * process.c (send_process): Don't bother breaking long line with EOF
    chars when talking to ttys any more.
    (wait_reading_process_output): Output a warning when called in such
    a way that it could block without being interruptible.

diff --git a/src/ChangeLog b/src/ChangeLog
index ad88dc8311..f9567b1308 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,5 +1,14 @@
 2010-04-13  Stefan Monnier  <monnier@iro.umontreal.ca>
 
+       Try to solve the problem of spurious EOF chars in long lines of text
+       sent to interactive subprocesses.
+       * sysdep.c (child_setup_tty): Do not enable ICANON any more.
+       (system_process_attributes): Remove unused var `ttotal'.
+       * process.c (send_process): Don't bother breaking long line with EOF
+       chars when talking to ttys any more.
+       (wait_reading_process_output): Output a warning when called in such
+       a way that it could block without being interruptible.
+
        Try to detect file modification within the same second.
        * buffer.h (struct buffer): New field modtime_size.
        * buffer.c (reset_buffer): Initialize it.
diff --git a/src/process.c b/src/process.c
index 34aa2c4fcf..7e8f4cc57b 100644
--- a/src/process.c
+++ b/src/process.c
@@ -4643,6 +4643,10 @@ wait_reading_process_output (time_limit, microsecs, 
read_kbd, do_display,
   FD_ZERO (&Connecting);
 #endif
 
+  if (time_limit == 0 && wait_proc && !NILP (Vinhibit_quit)
+      && !(CONSP (wait_proc->status) && EQ (XCAR (wait_proc->status), Qexit)))
+    message ("Blocking call to accept-process-output with quit inhibited!!");
+
   /* If wait_proc is a process to watch, set wait_channel accordingly.  */
   if (wait_proc != NULL)
     wait_channel = wait_proc->infd;
@@ -5768,34 +5772,6 @@ send_process (proc, buf, len, object)
        {
          int this = len;
 
-         /* Decide how much data we can send in one batch.
-            Long lines need to be split into multiple batches.  */
-         if (p->pty_flag)
-           {
-             /* Starting this at zero is always correct when not the first
-                iteration because the previous iteration ended by sending C-d.
-                It may not be correct for the first iteration
-                if a partial line was sent in a separate send_process call.
-                If that proves worth handling, we need to save linepos
-                in the process object.  */
-             int linepos = 0;
-             unsigned char *ptr = (unsigned char *) buf;
-             unsigned char *end = (unsigned char *) buf + len;
-
-             /* Scan through this text for a line that is too long.  */
-             while (ptr != end && linepos < pty_max_bytes)
-               {
-                 if (*ptr == '\n')
-                   linepos = 0;
-                 else
-                   linepos++;
-                 ptr++;
-               }
-             /* If we found one, break the line there
-                and put in a C-d to force the buffer through.  */
-             this = ptr - buf;
-           }
-
          /* Send this batch, using one or more write calls.  */
          while (this > 0)
            {
@@ -5899,11 +5875,6 @@ send_process (proc, buf, len, object)
              len -= rv;
              this -= rv;
            }
-
-         /* If we sent just part of the string, put in an EOF (C-d)
-            to force it through, before we send the rest.  */
-         if (len > 0)
-           Fprocess_send_eof (proc);
        }
     }
   else
diff --git a/src/sysdep.c b/src/sysdep.c
index 37e7dfbaf9..506af23ef3 100644
--- a/src/sysdep.c
+++ b/src/sysdep.c
@@ -529,8 +529,6 @@ child_setup_tty (out)
 #endif
   s.main.c_oflag &= ~TAB3;     /* Disable tab expansion */
   s.main.c_cflag = (s.main.c_cflag & ~CSIZE) | CS8; /* Don't strip 8th bit */
-  s.main.c_lflag |= ICANON;    /* Enable erase/kill and eof processing */
-  s.main.c_cc[VEOF] = 04;      /* insure that EOF is Control-D */
   s.main.c_cc[VERASE] = CDISABLE;      /* disable erase processing */
   s.main.c_cc[VKILL] = CDISABLE;       /* disable kill processing */
 
@@ -560,7 +558,6 @@ child_setup_tty (out)
   /* rms: Formerly it set s.main.c_cc[VINTR] to 0377 here
      unconditionally.  Then a SIGNALS_VIA_CHARACTERS conditional
      would force it to 0377.  That looks like duplicated code.  */
-  s.main.c_cc[VEOL] = CDISABLE;
   s.main.c_cflag = (s.main.c_cflag & ~CBAUD) | B9600; /* baud rate sanity */
 #endif /* AIX */
 
@@ -573,6 +570,18 @@ child_setup_tty (out)
   s.main.sg_kill = 0377;
   s.lmode = LLITOUT | s.lmode;        /* Don't strip 8th bit */
 
+  /* We used to enable ICANON (and set VEOF to 04), but this leads to
+     problems where process.c wants to send EOFs every once in a while
+     to force the output, which leads to weird effects when the
+     subprocess has disabled ICANON and ends up seeing those spurious
+     extra EOFs.  So we don't send EOFs any more in
+     process.c:send_process, and instead we disable ICANON by default,
+     so if a subsprocess sets up ICANON, it's his problem (or the Elisp
+     package that talks to it) to deal with lines that are too long.  */
+  s.main.c_lflag &= ~ICANON;   /* Disable line editing and eof processing */
+  s.main.c_cc[VMIN] = 1;
+  s.main.c_cc[VTIME] = 0;
+
 #endif /* not HAVE_TERMIO */
 
   EMACS_SET_TTY (out, &s, 0);
@@ -3344,7 +3353,7 @@ system_process_attributes (Lisp_Object pid)
   unsigned long minflt, majflt, cminflt, cmajflt, vsize;
   time_t sec;
   unsigned usec;
-  EMACS_TIME tnow, tstart, tboot, telapsed,ttotal;
+  EMACS_TIME tnow, tstart, tboot, telapsed;
   double pcpu, pmem;
   Lisp_Object attrs = Qnil;
   Lisp_Object cmd_str, decoded_cmd, tem;


-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





reply via email to

[Prev in Thread] Current Thread [Next in Thread]