elves / elvish

Powerful scripting language & versatile interactive shell

Home Page:https://elv.sh/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Elvish forces 4kb MAX_ARG_LEN?

vendion opened this issue · comments

Using Elvish 0.18.0 installed on Arch Linux it seems that MAX_ARG_LEN get forced to be 4kb. This hasn't been an issue until recently, when I tried to use Kitty Term's special SSH command and got an error due to MAX_ARG_LEN being set to 4128. It does seem to be Elvish that is setting this as if I launch say ZSH and use ulimit I can see that it has a MAX_ARG_LEN value of 8192.

Is this something that is changeable, or is it currently a hard set limit?

The first thing to note is that 4kb is 4096, not 4128. The second thing to note is that the kernel ARG_MAX variable limits the sum of the size of all environment variables and command line arguments. On every Linux system I use that defaults to 2MB (2048KB). Also, the ulimit command does not report, or allow, that value to be modified so it's not clear what you're looking at (maybe the stack size limit?). You can use getconf to view the limit:

elvish> getconf ARG_MAX
2097152

Also, each individual argument is limited to 128kb. Here is a simple demonstration:

[tty 136]:1:1: /bin/echo (repeat 16 (repeat (- (* 1024 128) 1) x | str:join '')) | wc -c
elvish> /bin/echo (repeat 15 (repeat (- (* 1024 128) 1) x | str:join '')) | wc -c
1966080
elvish> /bin/echo (repeat 16 (repeat (- (* 1024 128) 1) x | str:join '')) | wc -c
0
Exception: fork/exec /bin/echo: argument list too long

@vendion, You'll need to provide more information, such as the actual command(s) you ran, for us to provide more help.

There hasn't been any changes in Elvish's code related to this. This is either a change in Arch Linux's package or in the Go compiler.

I also can't find my doc on MAX_ARG_LEN - is it actually MAX_ARG_STRLEN?

@krader1961 sorry if my original post didn't include enough info, but I did link to the issue I filed against Kitty term about the issue where the author pointed out the problem.

kovidgoyal/kitty#5971

In short this is the command I ran which produced the error is below:

vendion on Vili ~ took 556ms
✦ ✗ kitty +kitten ssh freebsd@vendion.me
Error: too long arguments: argv[20] len (5056) >= MAX_ARG_LEN (4128)
Exception: kitty exited with 1
[tty 2], line 1: kitty +kitten ssh freebsd@vendion.me

This "kitten" is a special command in Kitty Term that uses SSH then installs/updates the terminfo file for Kitty on the remote box. It works with ZSH but not with Elvish.

@vendion, Note that the error message is from Kitty, not Elvish. If you copy/paste my demonstration command into an Elvish shell on your system you can easily verify that Elvish allows more than 4kb of arguments. Also, what happens if you simply enter ssh freebsd@vendion.me at an Elvish prompt? I'll bet it works. My guess is that the ssh "kitten" you are using assumes either as POSIX shell (which Elvish is not) or is explicitly detecting when you use Zsh and adapts itself accordingly.

And from the ssh kitten documentation:

When connecting to BSD hosts, it is possible the bootstrap script will fail or run slowly, because the default shells are crippled in various ways. Your best bet is to install Python on the remote, make sure the login shell is something POSIX sh compliant, and use python as the interpreter in ssh.conf.

It looks to me like using Elvish either requires a non-standard Kitty config or simply can't be made to work. Again, this has nothing to do with a hypothesized (non-existent) Elvish limitation on the length of command arguments.

Also, what happens if you simply enter ssh freebsd@vendion.me at an Elvish prompt?

Yes it does work, the whole point or the ssh kitten is that once it connects to the remote system it installs/updates the terminfo for Kitty to avoid issues on the remote system.

My guess is that the ssh "kitten" you are using assumes either as POSIX shell (which Elvish is not) or is explicitly detecting when you use Zsh and adapts itself accordingly.

I am aware that Elvish is not POSIX-compliant, but you may be on to something there. I was just going off the information the Author of Kitty Term gave when I originally reported the issue there. Maybe they didn't see what shell I'm using, or know about Evish and just wrote it off.

Anyways, I greatly appreciate your help and until/unless Kitty adds support for Elvish I'll just have to deal with doing it myself.

Maybe they didn't see what shell I'm using, or know about Evish and just wrote it off.

That would be my guess. I read your Kitty issue and my reaction was the person who responded to you didn't know what they are talking about. They certainly should have recognized that the error message was from Kitty itself rather than the command shell. Many similar mechanisms, such as those for creating virtual environments for Python, Conda, etc. depend on recognizing, and supporting, the shell you are running. That person should have noticed your mention of "Elvish" and asked themself if it was a shell supported by the Kitty "ssh kitten".

By the way, I'm still curious if you have confirmed to your satisfaction, whether using my example or some other method, that Elvish does, in fact, support command line arguments larger than 4kb on your systems. And how you did so.

By the way, I'm still curious if you have confirmed to your satisfaction, whether using my example or some other method, that Elvish does, in fact, support command line arguments larger than 4kb on your systems. And how you did so.

Yes, I ran your example and got the following

(Arch Linux box)

vendion on Vili ~ took 27s
✦ ➜ /bin/echo (repeat 15 (repeat (- (* 1024 128) 1) x | str:join '')) | wc -c
1966080

(FreeBSD box)

~> use str
~> /bin/echo (repeat 15 (repeat (- (* 1024 128) 1) x | str:join '')) | wc -c
       0
Exception: fork/exec /bin/echo: argument list too long
[tty 8], line 1: /bin/echo (repeat 15 (repeat (- (* 1024 128) 1) x | str:join '')) | wc -c
~> /bin/echo (repeat 15 (repeat (- (* 1024 64) 1) x | str:join '')) | wc -c
       0
Exception: fork/exec /bin/echo: argument list too long
[tty 9], line 1: /bin/echo (repeat 15 (repeat (- (* 1024 64) 1) x | str:join '')) | wc -c
~> /bin/echo (repeat 15 (repeat (- (* 1024 32) 1) x | str:join '')) | wc -c
  491520

The FreeBSD behavior is not surprising because its default ARG_MAX is just 512KB versus 2MB for Linux:

> getconf ARG_MAX
524288

If you change the repeat 15 to repeat 3 (i.e., three args of 128KB each) it would succeed.