Re: System shutdown signal on Windows (was Re: [GENERAL])

2014-07-24 Thread Krystian Bigaj
On 24 July 2014 07:51, Kalai R  wrote:

> Thank You so much Krystian Bigaj.
>
> Since last 2 years I had suffering this problem. But today I got solution
> from you.
> I am developing .Net application with Postgres.
> I am using WCF service (host as windows service) to connect postgres
> database.
>
> *My workaround: own service which will start/stop Postgres (mainly to wait
> for our service to stop, running initdb.exe in context of NetworkService,
> etc.).*
> *I've also written small Postgres module loaded via
> shared_preload_libraries which will call SetConsoleCtrlHandler, and my
> HandlerRoutine which simply returns TRUE. Because of
> this pg_console_handler won't be called (so no processing
> CTRL_SHUTDOWN_EVENT by any Postgress process).*
>
> * I need to wait first that our service stops, and then I let Postgres to
> stop (I have my own service - not pg_ctl - which will start/stop
> postgres.exe process).*
>
>
> I have similar situation to you. I also want create my own service to
> start /stop postgres. Please let me know how to start/stop postgres without
> pg_ctl. Could you share code for your small postgres module loaded via
> shared_preloaded libraries?
>
How to start postgres you can find here:
http://www.postgresql.org/docs/9.3/static/server-start.html
You could even use pg_ctl to start/stop postgres.exe process from your
service, but not using pg_ctl as service handler - I think that this should
be sufficient for you, and it's very easy to do, just simply run:
- pg_ctl.exe start -D "data dir" -o "--shared_preload_libraries=your.dll"
and to stop run:
- pg_ctl.exe stop D "data dir"
from your service.

For additional parameters read docs at:
http://www.postgresql.org/docs/9.3/static/app-pg-ctl.html

My PG module looks like this (pseudo code, my code is in Delphi):

dllMain(...)
{
switch(reason)
case DLL_PROCESS_ATTACH:
  SetConsoleCtrlHandler(HandlerRoutine, TRUE);

 case DLL_PROCESS_DETACH:
  SetConsoleCtrlHandler(HandlerRoutine, FALSE);
}

BOOL HandlerRoutine(...)
{
  return TRUE; // this will prevent call to next handler routine declared
in postgres process: src\backend\port\win32\singal.c: pg_console_handler <-
won't be called
}

Also that DLL module must export function Pg_magic_func which returns
static/global pointer to initialized Pg_magic_struct structure:
http://doxygen.postgresql.org/structPg__magic__struct.html

To start/stop postgres.exe I'm using:
- CreateProcess - starting postgres.exe, here I'm adding that
--shared_preload_libraries
- CallNamedPipe - sending stop or ping signal (parts of code
from src\port\kill.c)
- RegisterWaitForSingleObject - notification if postgres.exe process will
be abnormally terminated (in that case I do simple logging and terminating
my DB service - to not leave zombie service without really working
postgres.exe)
- pg_isready.exe - while starting service I'm waitng for Postgres to be
ready to accecpt connections, if it's ready, then I finally set my db
service state as running.
- on service start I'm checking if any postgres.exe is running on my
cluster directory, and I'm sending SIGTERM to it, and waiting for process
terminate
- stopping service: before I will send SIGINT signal to postgres, first I
wait for my main service appication to close clearly.
- my DB service also creates database cluster (initdb.exe) - because it's
too complicated to run initdb.exe on NetworkService while running on user
session (I know that I could use cacls/icacls - and I did before, but I had
customers who had mess in ACLs on installation drive)

Best regards,
Krystian Bigaj


Re: System shutdown signal on Windows (was Re: [GENERAL])

2014-07-23 Thread Kalai R
Thank You so much Krystian Bigaj.

Since last 2 years I had suffering this problem. But today I got solution
from you.
I am developing .Net application with Postgres.
I am using WCF service (host as windows service) to connect postgres
database.

*My workaround: own service which will start/stop Postgres (mainly to wait
for our service to stop, running initdb.exe in context of NetworkService,
etc.).*
*I've also written small Postgres module loaded via
shared_preload_libraries which will call SetConsoleCtrlHandler, and my
HandlerRoutine which simply returns TRUE. Because of
this pg_console_handler won't be called (so no processing
CTRL_SHUTDOWN_EVENT by any Postgress process).*

* I need to wait first that our service stops, and then I let Postgres to
stop (I have my own service - not pg_ctl - which will start/stop
postgres.exe process).*


I have similar situation to you. I also want create my own service to start
/stop postgres. Please let me know how to start/stop postgres without
pg_ctl. Could you share code for your small postgres module loaded via
shared_preloaded libraries?


Thanks & Regards
Kalai



On Thu, Jul 24, 2014 at 3:59 AM, Krystian Bigaj 
wrote:

> On 23 July 2014 22:16, Tom Lane  wrote:
>
>> Krystian Bigaj  writes:
>> > - when pg_console_handler receives CTRL_SHUTDOWN_EVENT from OS, then it
>> > calls pg_queue_signal(SIGINT).
>>
>> > Problems:
>> > - when OS is in shutdown path, then it sends CTRL_SHUTDOWN_EVENT, and
>> *all*
>> > Postgres processes (main and sub/forked) will call
>> pg_queue_signal(SIGINT)
>> > - so main and sub processes will start to shutdown independently? Can
>> this
>> > have any bad consequences?
>>
>> Hm.  We ought to have that sending SIGTERM instead, so as to mimic the
>> situation when Unix "init" is trying to shut down the system.  It might be
>> that SIGINT will more or less work, but the postmaster logic is designed
>> to work with global SIGTERM as being the clean-up-ASAP trigger.  As an
>> example, backends servicing remote applications (which will *not* have
>> already gotten killed) would not exit in response to SIGINT.
>>
>> > I think that CTRL_SHUTDOWN_EVENT should be removed from
>> pg_console_handler,
>>
>> That does not sound like a good idea, at least not if Windows has the
>> same behavior as "init" does of proceeding to hard kills after some
>> grace period.
>>
>> regards, tom lane
>>
>
> I'm not really familiar with Unix and it's SIG-commands. I know only
> about SIGINT/SIGTERM from Postgres documentation.
>
> However form what I see is that when Postgress is running by pg_ctl from
> service, then it will receive SIGINT (independently and in general in
> unspecified order)
> - *each* postgres.exe process will queue itself SIGINT (because of
> CTRL_SHUTDOWN_EVENT),
> - pg_ctl will send SIGINT to main postmaster process (and possibly it will
> pass that command to sub-processes)
> So there are two independent paths where SIGINT are sent, and pg_ctl
> doesn't have really a control when postgres.exe receives SIGINT.
> This CTRL_SHUTDOWN_EVENT is not used when postgres.exe is run on *user
> session* - so removing it won't change anything.
>
> I see only two cases where CTRL_SHUTDOWN_EVENT might be need (all of there
> where postgres.exe is run on service session):
> - postgres.exe run by pg_ctl.exe, but pg_ctl service process was
> terminated/killed, and then system was shutdown
> - someone starts postgres.exe from own service, but doesn't send
> SIGINT/SIGTERM command to postgres.exe on service system shutdown (but he
> must for service stop)
> As I previously wrote, I have workaround for it, so if you think that this
> change would break compatibility and don't want to change it, then I'm
> really fine with it.
>
> However I've probably found something with pg_ctl.c regarding shutdown and
> maybe that suspicious postgres.exe process termination on Windows.
>
> 1) shutdownEvent is signaled in pgwin32_ServiceMain
> by SERVICE_CONTROL_STOP/SERVICE_CONTROL_SHUTDOWN in pgwin32_ServiceHandler
> There is dwWaitHint = 1.
>
> 2)
> ...
>   /* Wait for quit... */
> ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
>
> pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
> switch (ret)
>  {
> case WAIT_OBJECT_0: /* shutdown event */
>  kill(postmasterPID, SIGINT);
>
> /*
>  * Increment the checkpoint and try again Abort after 12
>  * checkpoints as the postmaster has probably hung
>  */
> while (WaitForSingleObject(postmasterProcess, 5000) == WAIT_TIMEOUT &&
> status.dwCheckPoint < 12)
>  status.dwCheckPoint++; < missing call
> to pgwin32_SetServiceStatus(SERVICE_STOP_PENDING)
> or SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
>  break;
> ...
>
> There is incremented dwCheckPoint every 5000ms, but that status is not
> updated (missing pgwin32_SetServiceStatus/SetServiceStatus), so SCM after
> 10s (dwWaitHint = 1) will not receive incremented dwCheckPoint, and
> it's allowed to kill that process (because