Hello Robin. First of all, thanks for using this MUA and reporting this issue.
Robin Humble wrote in <[email protected]>: |on current RHEL9 and Fedora40, and also on s-nail git master, I ran |into an issue that halts a backgrounded script connected to a tty. | |as an example on RHEL9 -> | | $ ( echo blah | Mail root ) & |[1] 2754649 | $ ^M^M^M^M^C^C | |[1]+ Stopped ( echo blah | Mail root ) | $ fg |( echo blah | Mail root ) | $ | |the mail is sent, but the calling script (just a subshell in this case) |is Stopped. the calling tty is confused and shows control characters. |^C is needed to get back to the shell. | |I dug a bit deeper and it seems s-nail mistakenly tries to set |terminal options in this use-case? Yes and no. You can work around this by redirecting standard output to /dev/null: | $ ( echo blah | Mail root >/dev/null) & This will do what you want. |I gather that tcsetattr causes the backgrounded script to get sent |SIGTTOU and the entire script (not just s-nail) goes to Stopped state. |mail gets sent, but the calling script is halted. |scripts launched via cron and systemd work fine, presumably because |those scripts are detached from a tty. | |I've narrowed the problem down to the below part of git master, but I |don't know enough about s-nail (or signals, ttys, ...) to fix it. [..termios stuff..] |can you please help? | |is there an internal mode that describes this style of usage of s-nail? |if so, maybe that could be used to avoid all tcsetattr entirely? Yes. I yet have to check *why* this went wrong, the problem is that everywhere we do eg if(n_psonce & n_PSO_TTYANY){ but the real condition should be as in mx_termios_controller_setup(), what!=mx_TERMIOS_SETUP_STARTUP: /* Semantics are a bit hairy and cast in stone in the manual, and * scattered all over the place, at least $COLUMNS, $LINES, -# */ if(!su_state_has(su_STATE_REPRODUCIBLE) && ((n_psonce & n_PSO_INTERACTIVE) || ((n_psonce & n_PSO_TTYANY) && (n_poption & n_PO_BATCH_FLAG)) ) ){ Moreover TTYANY is n_PSO_TTYANY = n_PSO_TTYIN | n_PSO_TTYOUT, /* mx_tty_fp = TTY */ so (x&TTYANY)==TTYANY it should likely be, and INTERACTIVE is /* Assume we are interactive, then. * This state will become unset later for n_PO_QUICKRUN_MASK! */ if((n_psonce & n_PSO_TTYANY) == n_PSO_TTYANY) n_psonce |= n_PSO_INTERACTIVE; And before we have a big TODO /* TODO This is wrong: interactive is STDIN/STDERR for a POSIX sh(1). * TODO For now we get this wrong, all over the place, as this software * TODO has always been developed with stdout as an output channel. * TODO Start doing it right for at least explicit terminal-related things, * TODO but v15 should use ONLY this, also for terminal input! */ So if we were doing right the above instead really had to redirect stderr to /dev/null, .. yet that is not correct at the moment, too. I .. still try to wrap my head what would be the right thing to do. The POSIX standard says for the shell: APPLICATION USAGE Standard input and standard error are the files that determine whether a shell is interactive when -i is not specified. For example: sh > file and: sh 2> file create interactive and non-interactive shells, respectively. Although both accept terminal input, the results of error conditions are different[.] But then again we currently *only* support standard input as a terminal, so. Hm. Thanks for reporting this issue! Again, direct success via redirecting standard output in addition $ ( echo blah | Mail root >/dev/null) & a real patch will be in v14.10 somewhen in fall i hope. (Adding your email to THANKS is ok?) Ciao! --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt)
