Re: protect dll lib initialisation against any exception, for 8.5

From: Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: protect dll lib initialisation against any exception, for 8.5
Date: 2009-04-02 02:46:34
Message-ID: 162867790904011946n1c032b63s7e14036cdf2df120@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

2009/4/2 Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>:
> Pavel Stehule <pavel(dot)stehule(at)gmail(dot)com> writes:
>> attached patch allows raising exception from _PG_init function as was
>> discussed before.
>
> I fooled around with this and came up with the attached improved
> version, which allows reporting the full error status.  However,
> after thinking some more I feel that this is probably a cure worse
> than the disease.  If we simply leave the code as it stands, an
> elog(ERROR) in an init function doesn't corrupt dfmgr.c's internal list,
> which is what I had been fearing when I complained about the issue.
> The worst that happens is that we leave the library loaded and leak
> a little bit of memory.  Unloading the library, as the patch does,
> could easily make things worse not better.  Consider the not-unlikely
> case that the library installs itself in a few callback hooks and
> then fails.  If we unload the library, those hooks represent
> *guaranteed* core dumps on next use.  If we don't unload, the hook
> functions might or might not work too well --- presumably not everything
> they need has been initialized --- but it's hard to imagine an outcome
> that's worse than a guaranteed core dump.
>
> So I'm thinking this is really unnecessary and we should leave well
> enough alone.
>

I see it. I thing , an safety of this exception should be solved only
by programmer. It's important to release all hooks, and then raise an
exception. It is in developer responsibility.

regards
Pavel Stehule

>                        regards, tom lane
>
>
> Index: dfmgr.c
> ===================================================================
> RCS file: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v
> retrieving revision 1.98
> diff -c -r1.98 dfmgr.c
> *** dfmgr.c     1 Jan 2009 17:23:51 -0000       1.98
> --- dfmgr.c     1 Apr 2009 23:41:37 -0000
> ***************
> *** 178,184 ****
>  static void *
>  internal_load_library(const char *libname)
>  {
> !       DynamicFileList *file_scanner;
>        PGModuleMagicFunction magic_func;
>        char       *load_error;
>        struct stat stat_buf;
> --- 178,184 ----
>  static void *
>  internal_load_library(const char *libname)
>  {
> !       DynamicFileList * volatile file_scanner;
>        PGModuleMagicFunction magic_func;
>        char       *load_error;
>        struct stat stat_buf;
> ***************
> *** 277,287 ****
>                }
>
>                /*
> !                * If the library has a _PG_init() function, call it.
>                 */
>                PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init");
>                if (PG_init)
> !                       (*PG_init) ();
>
>                /* OK to link it into list */
>                if (file_list == NULL)
> --- 277,329 ----
>                }
>
>                /*
> !                * If the library has a _PG_init() function, call it.  Guard against
> !                * the function possibly throwing elog(ERROR).
>                 */
>                PG_init = (PG_init_t) pg_dlsym(file_scanner->handle, "_PG_init");
>                if (PG_init)
> !               {
> !                       MemoryContext   oldcontext = CurrentMemoryContext;
> !
> !                       PG_TRY();
> !                       {
> !                               (*PG_init) ();
> !                       }
> !                       PG_CATCH();
> !                       {
> !                               ErrorData  *edata;
> !
> !                               /* fetch the error status so we can change it */
> !                               MemoryContextSwitchTo(oldcontext);
> !                               edata = CopyErrorData();
> !                               FlushErrorState();
> !
> !                               /*
> !                                * The const pointers in the error status very likely point
> !                                * at constant strings in the library, which we are about to
> !                                * unload.  Copy them so we don't dump core while reporting
> !                                * the error.  This might leak a bit of memory but it
> !                                * beats the alternatives.
> !                                */
> !                               if (edata->filename)
> !                                       edata->filename = pstrdup(edata->filename);
> !                               if (edata->funcname)
> !                                       edata->funcname = pstrdup(edata->funcname);
> !                               if (edata->domain)
> !                                       edata->domain = pstrdup(edata->domain);
> !
> !                               /* library might have already called some of its functions */
> !                               clear_external_function_hash(file_scanner->handle);
> !
> !                               /* try to unlink library */
> !                               pg_dlclose(file_scanner->handle);
> !                               free((char *) file_scanner);
> !
> !                               /* complain */
> !                               ReThrowError(edata);
> !                       }
> !                       PG_END_TRY();
> !               }
>
>                /* OK to link it into list */
>                if (file_list == NULL)
>
>

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2009-04-02 02:58:24 Re: protect dll lib initialisation against any exception, for 8.5
Previous Message Tom Lane 2009-04-02 01:37:01 Re: tuplestore API problem