tramp-hangs when command line exceeds 256 characters; MAX_CANON limit.

Stacey Marshall <[email protected]> Thu, 08 May 2025 13:30:17 +0100
Newsgroups gmane.emacs.tramp
Message-ID <[email protected]>
Hi tramp-devel,

   Cirling back to remote command execution command line length issue
   seen with tramp upon connection to Solaris host.  Michael Albinus
   observed the issue was due to a max line length of 256 characters.
   - [Re: tramp hangs opening a file, Emacs 30.1 tramp-version
     "2.7.1.30.1" an]

   Today I was wanting to use [Man-support-remote-systems] to see 
Solaris
   manual page within emacs running on Darmin (sequoia 15.4.1).  From 
the
   debug buffer I could once again see the command being executed was
   much longer than 256 characters, and the I/O buffer showing many ^G
   characters. Which is what was also observed with the loooongish file
   names issues.

   Searching tramp-devel archive I came across [Re: tramp 2.26 emacs 
24.3
   plink] which included a link to [Solaris limitation on command line -
   Oracle Forums]

   Their testing showed that it wasn't down to shell input length, but
   instead the setting of `MAX_CANON' (from limits.h):
   ,----
   | #define	MAX_CANON	256	/* max bytes in line for canonical processing 
*/
   `----

   With a suggestion that `expect' script should include
   ,----
   | set stty_init raw
   `----

   To which expect(1) states
         will cause further spawned processes's terminals to start
         in raw mode.

   Looking at stty(1) *raw* on Solaris is:
   ,----
   | stty cs8 -icanon min 1 time 0 -isig -xcase -inpck -opost
   `----


   Looking in tramp I see that `tramp-sh.el' runs `stty' a few times, 
and
   nicely captures current settings to debug buffer too.  Of particular
   note is `tramp-pipe-stty-setting':
   ,----
   | (defcustom tramp-pipe-stty-settings "-icanon min 1 time 0"
   |   "How to prevent blocking read in pipeline processes.
   | This is used in `make-process' with `connection-type' `pipe'."
   |   :group 'tramp
   |   :version "29.3"
   |   :type '(choice (const :tag "Use size limit" "-icanon min 1 time 
0")
   | 		 (const :tag "Use timeout" "-icanon min 0 time 1")
   | 		 string))
   `----

   For a simple test then I modified `tramp-sh-handle-make-process' to
   always apply it:
   ,----
   | $ git diff
   | diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
   | index 618fc386e58..3ecf92f7d28 100644
   | --- a/lisp/net/tramp-sh.el
   | +++ b/lisp/net/tramp-sh.el
   | @@ -3115,7 +3115,7 @@ tramp-sh-handle-make-process
   |                         (let ((pid (tramp-send-command-and-read v 
"echo $$")))
   |                           (setq p (tramp-get-connection-process v))
   |                           (process-put p 'remote-pid pid))
   | -                       (when (meme connection-type '(nil pipe))
   | +;                      (when (memq connection-type '(nil pipe))
   |                           ;; Disable carriage return to newline
   |                           ;; translation.  This does not work on
   |                           ;; macOS, see Bug#50748.
   | @@ -3137,7 +3137,8 @@ tramp-sh-handle-make-process
   |                               "stty %s %s"
   |                               (if (tramp-check-remote-uname v 
"Darwin")
   |                                   "" "-icrnl")
   | -                             tramp-pipe-stty-settings)))
   | +                             tramp-pipe-stty-settings))
   | +;)
   |                         ;; `tramp-maybe-open-connection' and
   |                         ;; `tramp-send-command-and-read' could have
   |                         ;; trashed the connection buffer.  Remove
   `----

   Evaluated that function, cleaned connections, accessed remote buffer
   and ran man again, and it worked.

   Clearly this is a limited test and I may well have broken something
   else with these settings. Which from the manual page are:

   -icrnl
         do not map CR to NL on input.

   -icanon
         Disable canonical input (ERASE and KILL processing).  Does not
         set MIN or TIME.

   `min number' / `time number'
         Set the value of min or time to number. MIN and TIME are used 
in
         Non-Canonical mode input processing (-icanon).

   For the moment I shall carry-on and see what breaks, but hopefully
   more of what works now!


References:


[Re: tramp hangs opening a file, Emacs 30.1 tramp-version "2.7.1.30.1"
an]
<https://lists.gnu.org/archive/html/tramp-devel/2025-04/msg00001.html>

[Man-support-remote-systems]
<https://www.gnu.org/software/emacs/manual/html_node/emacs/Man-Page.html>

[Re: tramp 2.26 emacs 24.3 plink]
<https://lists.gnu.org/archive/html/tramp-devel/2014-09/msg00041.html>

[Solaris limitation on command line - Oracle Forums]
<https://forums.oracle.com/ords/apexds/post/solaris-limitation-on-command-line-9450>


--
Stace