so 20. 3. 2021 v 23:45 odesílatel Thomas Munro <thomas.mu...@gmail.com>
napsal:

> On Thu, Mar 4, 2021 at 11:28 PM Pavel Stehule <pavel.steh...@gmail.com>
> wrote:
> > čt 4. 3. 2021 v 7:37 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
> napsal:
> >> Here is a little bit updated patch - detection of end of any child
> process cannot be used on WIN32.
>
> Yeah, it's OK for me if this feature only works on Unix until the
> right person for the job shows up with a patch.  If there is no pspg
> on Windows, how would we even know if it works?
>
> > second version - after some thinking, I think the pager for \watch
> command should be controlled by option "pager" too.  When the pager is
> disabled on psql level, then the pager will not be used for \watch too.
>
> Makes sense.
>
> +            long        s = Min(i, 100L);
> +
> +            pg_usleep(1000L * s);
> +
> +            /*
> +             * in this moment an pager process can be only one child of
> +             * psql process. There cannot be other processes. So we can
> +             * detect end of any child process for fast detection of
> +             * pager process.
> +             *
> +             * This simple detection doesn't work on WIN32, because we
> +             * don't know handle of process created by _popen function.
> +             * Own implementation of _popen function based on
> CreateProcess
> +             * looks like overkill in this moment.
> +             */
> +            if (pagerpipe)
> +            {
> +
> +                int        status;
> +                pid_t    pid;
> +
> +                pid = waitpid(-1, &status, WNOHANG);
> +                if (pid)
> +                    break;
> +            }
> +
> +#endif
> +
>              if (cancel_pressed)
>                  break;
>
> I thought a bit about what we're really trying to achieve here.  We
> want to go to sleep until someone presses ^C, the pager exits, or a
> certain time is reached.  Here, we're waking up 10 times per second to
> check for exited child processes.  It works, but it does not spark
> joy.
>
> I thought about treating SIGCHLD the same way as we treat SIGINT: it
> could use the siglongjmp() trick for a non-local exit from the signal
> handler.  (Hmm... I wonder why that pre-existing code bothers to check
> cancel_pressed, considering it is running with
> sigint_interrupt_enabled = true so it won't even set the flag.)  It
> feels clever, but then you'd still have the repeating short
> pg_usleep() calls, for reasons described by commit 8c1a71d36f5.  I do
> not like sleep/poll loops.  Think of the polar bears.  I need to fix
> all of these, as a carbon emission offset for cfbot.
>
> Although there are probably several ways to do this efficiently, my
> first thought was: let's try sigtimedwait()!  If you block the signals
> first, you have a race-free way to wait for SIGINT (^C), SIGCHLD
> (pager exited) or a timeout you can specify.  I coded that up and it
> worked pretty nicely, but then I tried it on macOS too and it didn't
> compile -- Apple didn't implement that.  Blah.
>
> Next I tried sigwait().  That's already used in our tree, so it should
> be OK.  At first I thought that using SIGALRM to wake it up would be a
> bit too ugly and I was going to give up, but then I realised that an
> interval timer (one that automatically fires every X seconds) is
> exactly what we want here, and we can set it up just once at the start
> of do_watch() and cancel it at the end of do_watch().  With the
> attached patch you get exactly one sigwait() syscall of the correct
> duration per \watch cycle.
>
> Thoughts?  I put my changes into a separate patch for clarity, but
> they need some more tidying up.
>

yes, your solution is much better.

Pavel


> I'll look at the documentation next.
>

Reply via email to