Re: dynamic background workers, round two - Mailing list pgsql-hackers

From Andres Freund
Subject Re: dynamic background workers, round two
Date
Msg-id 20130827135025.GB24807@alap2.anarazel.de
Whole thread Raw
In response to Re: dynamic background workers, round two  (Robert Haas <robertmhaas@gmail.com>)
Responses Re: dynamic background workers, round two  (Robert Haas <robertmhaas@gmail.com>)
List pgsql-hackers
Hi Robert,

On 2013-08-17 12:08:17 -0400, Robert Haas wrote:
> On Sun, Aug 11, 2013 at 1:31 AM, Andres Freund <andres@anarazel.de> wrote:
> > So, I'd suggest something like:
> >
> > typedef enum BgwHandleStatus {
> >    BGWH_SUCCESS, /* sucessfully got status */
> >    BGWH_NOT_YET, /* worker hasn't started yet */
> >    BGWH_GONE, /* worker had been started, but shut down already */
> >    BGWH_POSTMASTER_DIED /* well, there you go */
> > } BgwHandleStatus;
> >
> >
> > BgwHandleStatus GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pid);
> > BgwHandleStatus WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pid);
> 
> OK, here's a patch that API.  I renamed the constants a bit, because a
> process that has stopped is not necessarily gone; it could be
> configured for restart.  But we can say that it is stopped, at the
> moment.
> 
> I'm not sure that this API is an improvement.  But I think it's OK, if
> you prefer it.

Thanks, looks more readable to me. I like code that tells me what it
does without having to look in other places ;)

> +  <function>RegisterDynamicBackgroundWorker(<type>BackgroundWorker
> +  *worker, BackgroundWorkerHandle **handle</type>)</function>.  Unlike
> +  <function>RegisterBackgroundWorker</>, which can only be called from within
> +  the postmaster, <function>RegisterDynamicBackgroundWorker</function> must be
> +  called from a regular backend.
>   </para>

s/which can only be called from within the posmaster/during initial
startup, via shared_preload_libraries/?

>    <para>
> +   When a background worker is registered using the
> +   <function>RegisterDynamicBackgroundWorker</function> function, it is
> +   possible for the backend performing the registration to obtain information
> +   the status of the worker.  Backends wishing to do this should pass the
> +   address of a <type>BackgroundWorkerHandle *</type> as the second argument
> +   to <function>RegisterDynamicBackgroundWorker</function>.  If the worker
> +   is successfully registered, this pointer will be initialized with an
> +   opaque handle that can subsequently be passed to
> +   <function>GetBackgroundWorkerPid(<parameter>BackgroundWorkerHandle *</parameter>, <parameter>pid_t
*</parameter>)</function>.
> +   This function can be used to poll the status of the worker: a return
> +   value of <literal>BGWH_NOT_YET_STARTED</> indicates that the worker has not
> +   yet been started by the postmaster; <literal>BGWH_STOPPED</literal>
> +   indicates that it has been started but is no longer running; and
> +   <literal>BGWH_STATED</literal> indicates that it is currently running.
> +   In this last case, the PID will also be returned via the second argument.
> +  </para>

s/STATED/STARTED/

> diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
> index f7ebd1a..6414291 100644
> --- a/src/backend/commands/async.c
> +++ b/src/backend/commands/async.c

> -#define InvalidPid                (-1)
> -

Hrmpf ;)

>  bool
> -RegisterDynamicBackgroundWorker(BackgroundWorker *worker)
> +RegisterDynamicBackgroundWorker(BackgroundWorker *worker,
> +                                BackgroundWorkerHandle **handle)
>  {

Hm. Not this patches fault, but We seem to allow bgw_start_time ==
BgWorkerStart_PostmasterStart here which doesn't make sense...

> +/*
> + * Get the PID of a dynamically-registered background worker.
> + *
> + * If the return value is InvalidPid, it indicates that the worker has not
> + * yet been started by the postmaster.
> + *
> + * If the return value is 0, it indicates that the worker was started by
> + * the postmaster but is no longer running.
> + *
> + * Any other return value is the PID of the running worker.
> + */
> +BgwHandleStatus
> +GetBackgroundWorkerPid(BackgroundWorkerHandle *handle, pid_t *pidp)
> +{
> +    BackgroundWorkerSlot *slot;
> +    pid_t    pid;
> +
> +    slot = &BackgroundWorkerData->slot[handle->slot];

Maybe add something like Assert(hanlde->slot < max_worker_processes);?

> +/*
> + * Wait for a background worker to start up.
> + *
> + * The return value is the same as for GetBackgroundWorkerPID, except that
> + * we only return InvalidPid if the postmaster has died (and therefore we
> + * know that the worker will never be started).
> + */
> +BgwHandleStatus
> +WaitForBackgroundWorkerStartup(BackgroundWorkerHandle *handle, pid_t *pidp)
> +{
> +    BgwHandleStatus    status;
> +    pid_t    pid;
> +    int        rc;
> +
> +    set_latch_on_sigusr1 = true;
> +
> +    PG_TRY();
> +    {
> +        for (;;)
> +        {
> +            status = GetBackgroundWorkerPid(handle, &pid);
> +            if (status != BGWH_NOT_YET_STARTED)
> +                break;
> +            rc = WaitLatch(&MyProc->procLatch,
> +                           WL_LATCH_SET | WL_POSTMASTER_DEATH, 0);
> +            if (rc & WL_POSTMASTER_DEATH)
> +            {
> +                status = BGWH_POSTMASTER_DIED;
> +                break;
> +            }
> +            ResetLatch(&MyProc->procLatch);
> +        }
> +    }
> +    PG_CATCH();
> +    {
> +        set_latch_on_sigusr1 = false;
> +        PG_RE_THROW();
> +    }
> +    PG_END_TRY();
> +
> +    set_latch_on_sigusr1 = false;
> +    *pidp = pid;
> +    return status;
> +}

Shouldn't that loop have a CHECK_FOR_INTERRUPTS()?

Theoretically this would unset set_latch_on_sigusr1 if it was previously
already set to 'true'. If you feel defensive you could safe the previous
value...

So, besides those I don't see much left to be done. I haven't tested
EXEC_BACKEND, but I don't anything specific to that here.

Greetings,

Andres Freund

-- Andres Freund                       http://www.2ndQuadrant.com/PostgreSQL Development, 24x7 Support, Training &
Services



pgsql-hackers by date:

Previous
From: Tom Lane
Date:
Subject: Re: UNNEST with multiple args, and TABLE with multiple funcs
Next
From: Andres Freund
Date:
Subject: Re: dynamic background workers, round two