Subject: Re: bug#76888: 31.0.50; start-process: Spawning child process: Invalid argument

From: Michael Albinus <[email-masked]>
Date: Mon, 17 Mar 2025 10:01:03 +0100

Eli Zaretskii <[email-masked]> writes:

Hi,

>> > > The first factor is that the value of shell-file-name sometimes gets
>> > > set buffer-locally in the "*Async Shell Command*" buffer. (This is
>> > > true for the Tramp code, when the buffer is reused. I don't know if it
>> > > is meaningful to ask whether it is true for the non-Tramp code.)
>> >
>> > If Tramp sets the buffer-local value in the "*Async Shell Command*"
>> > buffer, it should also set default-directory in that buffer.

It is vice-versa. Tramp sets a buffer-local value of shell-file-name in
"*Async Shell Command*" depending on the default-directory of that
buffer. In fact, it is a connection-local value (which is implemented
via buffer-local value).

The setting of the connection-local value is done in
tramp-integration.el:

--8<---------------cut here---------------start------------->8---
(defconst tramp-connection-local-default-shell-variables
  '((shell-file-name . "/bin/sh")
    (shell-command-switch . "-c"))
  "Default connection-local shell variables for remote connections.")
--8<---------------cut here---------------end--------------->8---

>> In 'shell-command' in "simple.el", 'start-process-shell-command'
>> is called after changing to the "*Async Shell Command*" buffer.
>>
>>         (let* ((buffer (get-buffer-create
>>                 (or output-buffer shell-command-buffer-name-async)))
>>                 [...])
>>           [...]
>>           (with-current-buffer buffer
>>         [...]
>>           (setq proc
>>             (start-process-shell-command "Shell" buffer command)))
>>
>> Then in the body of 'start-process-shell-command',
>>
>>   (start-process name buffer shell-file-name shell-command-switch command)
>
> That's a mistake: at least for local commands, the values of
> shell-file-name and shell-command-switch should come from the buffer
> that is current when the command is invoked.
>
> Let's wait for Michael to chime in and explain how these variables
> should be populated for remote shell commands; I guess
> connection-local variables should be consulted, but the relevant
> connection should be taken again from the buffer that is current when
> the command is invoked.

Tramp sets connection-local values for asynchronous processes in the
buffer which is given at start. Always.

>> > Buffer-local values should matter only when commands are invoked with
>> > that buffer the current buffer.  Which part(s) of your recipe do that?

We're speaking about connection-local values. And they are set in
Tramp's implementation of make-process.

>> The recipe does not do that. The command 'async-shell-command' is
>> invoked three times from dired buffers and never from the "*Async
>> Shell Command*" buffer.
>
> Then it's a clear bug.  I'm guessing the code in question never
> expected shell-command to have a buffer-local value (which is indeed
> an unusual and strange situation).  So maybe a simpler solution is to
> never make shell-command's value be buffer-local.

That's not possible if Tramp is in play with its connection-local
variables.

It seems to me that the problem is rather the re-use of the "*Async
Shell Command*" buffer even in case the default-directory changes. It
isn't a problem if this change is inside the same "remote" file system
Tramp offers virtually. But if the change means, that another remote
connection is established, or there is a change between remote and local
directory, I propose to use another (new) "*Async Shell Command*" buffer.

Best regards, Michael.