Hi Stuart,

Stuart Henderson wrote on Fri, Oct 29, 2021 at 01:59:38PM +0100:
> On 2021/10/29 14:08, Ingo Schwarze wrote:
>> Stuart Henderson wrote on Fri, Oct 29, 2021 at 10:53:41AM +0100:
>>> On 2021/10/28 23:19, Klemens Nanni wrote:
>>>> On Fri, Oct 29, 2021 at 12:57:54AM +0200, Ingo Schwarze wrote:

>>>>>   MANPAGER=firefox man -T html $(ifconfig -C)

>>>> This doesn't work if firefox is already running as the MANPAGER firefox
>>>> process exits immediately after sending the file/link to the running
>>>> process, which causes mandoc to exit after removing the temporary file,
>>>> by which time firefox fails to open the no longer exiting file.

>>> I use mutt_bgrun for things like this

>> I don't see how that can possibly help.

> Oh, of course you're right - I was confused between my helper
> scripts. The one I actually use for html in mutt looks like this,
> so it's not any user for MANPAGER..
> 
> tmp=`mktemp -d /tmp/mutthtml.XXXXXXXXX` || exit 1
> mhonarc -rcfile ~/.m2h_rcfile -single > $tmp/mail.html
> (chrome $tmp/mail.html 2>/dev/null; sleep 30; rm -r $tmp) &

Indeed, if i added sleep(30) to the place in question
in usr.bin/mandoc/main.c, i would expect quite an outrage...
A protest rally on my front lawn or something like that...

Then again, the man(1) process that is about to exit could maybe fork
a child before exiting.  The parent exiting right away makes sure that
the user gets back their shell prompt instantly after exiting the pager.
The child process, now being in the background, could sleep a few seconds
before deleting the temporary output files, then exit, too.

This does appear to successfully work around the firefox bug.
With the patch below, "MANPAGER=firefox man -T html ..."
now works reliably for me.

It does seem somewhat ugly, though, so i'm not sure whether i should
commit it.  In particular, fork(2)ing merely to go to the background
seems both cumbersome and expensive - admittedly, your script cited
above does the same, but that doesn't imply i have to like that, right?

Is there a cleaner way to let man(1) go into the background and
let the shell offer a fresh prompt while man(1) still sleeps,
without needing to fork(2)?

Yours,
  Ingo


Index: main.c
===================================================================
RCS file: /cvs/src/usr.bin/mandoc/main.c,v
retrieving revision 1.262
diff -u -p -r1.262 main.c
--- main.c      4 Oct 2021 21:28:50 -0000       1.262
+++ main.c      29 Oct 2021 14:12:08 -0000
@@ -1203,6 +1203,7 @@ woptions(char *arg, enum mandoc_os *os_e
 static void
 run_pager(struct outstate *outst, char *tag_target)
 {
+       const struct timespec delay = { 5, 0 };
        int      signum, status;
        pid_t    man_pgid, tc_pgid;
        pid_t    pager_pid, wait_pid;
@@ -1245,13 +1246,16 @@ run_pager(struct outstate *outst, char *
                if (wait_pid == -1) {
                        mandoc_msg(MANDOCERR_WAIT, 0, 0,
                            "%s", strerror(errno));
-                       break;
+                       return;
                }
                if (!WIFSTOPPED(status))
                        break;
 
                signum = WSTOPSIG(status);
        }
+       if (fork() > 0)
+               _exit(mandoc_msg_getrc());
+       nanosleep(&delay, NULL);
 }
 
 static pid_t

Reply via email to