Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commita4c40f1

Browse files
committed
Here's an attempt at new socket and signal code for win32.
It works on the principle of turning sockets into non-blocking, and thenemulate blocking behaviour on top of that, while allowing signals torun. Signals are now implemented using an event instead of APCs, thusgetting rid of the issue of APCs not being compatible with "old style"sockets functions.It also moves the win32 specific code away from pqsignal.h/c intoport/win32, and also removes the "thread style workaround" of the APCissue previously in place.In order to make things work, a few things are also changed in pgstat.c:1) There is now a separate pipe to the collector and the bufferer. Thisis required because the pipe will otherwise only be signalled in one ofthe processes when the postmaster goes down. The MS winsock code forselect() must have some kind of workaround for this behaviour, but Ihave found no stable way of doing that. You really are not supposed touse the same socket from more than one process (unless you useWSADuplicateSocket(), in which case the docs specifically say that onlyone will be flagged).2) The check for "postmaster death" is moved into a separate select()call after the main loop. The previous behaviour select():ed on thepostmaster pipe, while later explicitly saying "we do NOT check forpostmaster exit inside the loop".The issue was that the code relies on the same select() call seeing boththe postmaster pipe *and* the pgstat pipe go away. This does not alwayshappen, and it appears that useing WSAEventSelect() makes it even morecommon that it does not.Since it's only called when the process exits, I don't think using aseparate select() call will have any significant impact on how the statscollector works.Magnus Hagander
1 parentabdabeb commita4c40f1

File tree

11 files changed

+831
-374
lines changed

11 files changed

+831
-374
lines changed

‎src/backend/libpq/pqsignal.c

Lines changed: 4 additions & 291 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.32 2004/02/18 16:25:12 momjian Exp $
12+
* $PostgreSQL: pgsql/src/backend/libpq/pqsignal.c,v 1.33 2004/04/12 16:19:18 momjian Exp $
1313
*
1414
* NOTES
1515
*This shouldn't be in libpq, but the monitor and some other
@@ -38,9 +38,6 @@
3838
*is to do signal-handler reinstallation, which doesn't work well
3939
*at all.
4040
* ------------------------------------------------------------------------*/
41-
#ifdefWIN32
42-
#define_WIN32_WINNT 0x0400
43-
#endif
4441

4542
#include"postgres.h"
4643

@@ -131,7 +128,9 @@ pqinitmask(void)
131128
}
132129

133130

131+
/* Win32 signal handling is in backend/port/win32/signal.c */
134132
#ifndefWIN32
133+
135134
/*
136135
* Set up a signal handler
137136
*/
@@ -154,290 +153,4 @@ pqsignal(int signo, pqsigfunc func)
154153
returnoact.sa_handler;
155154
#endif/* !HAVE_POSIX_SIGNALS */
156155
}
157-
158-
159-
#else
160-
161-
162-
/* Win32 specific signals code */
163-
164-
/* pg_signal_crit_sec is used to protect only pg_signal_queue. That is the only
165-
* variable that can be accessed from the signal sending threads! */
166-
staticCRITICAL_SECTIONpg_signal_crit_sec;
167-
staticintpg_signal_queue;
168-
169-
#definePG_SIGNAL_COUNT 32
170-
staticpqsigfuncpg_signal_array[PG_SIGNAL_COUNT];
171-
staticpqsigfuncpg_signal_defaults[PG_SIGNAL_COUNT];
172-
staticintpg_signal_mask;
173-
174-
HANDLEpgwin32_main_thread_handle;
175-
176-
/* Signal handling thread function */
177-
staticDWORDWINAPIpg_signal_thread(LPVOIDparam);
178-
staticBOOLWINAPIpg_console_handler(DWORDdwCtrlType);
179-
180-
/* Initialization */
181-
void
182-
pgwin32_signal_initialize(void)
183-
{
184-
inti;
185-
HANDLEsignal_thread_handle;
186-
187-
InitializeCriticalSection(&pg_signal_crit_sec);
188-
189-
for (i=0;i<PG_SIGNAL_COUNT;i++)
190-
{
191-
pg_signal_array[i]=SIG_DFL;
192-
pg_signal_defaults[i]=SIG_IGN;
193-
}
194-
pg_signal_mask=0;
195-
pg_signal_queue=0;
196-
197-
/* Get handle to main thread so we can post calls to it later */
198-
if (!DuplicateHandle(GetCurrentProcess(),GetCurrentThread(),
199-
GetCurrentProcess(),&pgwin32_main_thread_handle,
200-
0, FALSE,DUPLICATE_SAME_ACCESS))
201-
ereport(FATAL,
202-
(errmsg_internal("Failed to get main thread handle!")));
203-
204-
/* Create thread for handling signals */
205-
signal_thread_handle=CreateThread(NULL,0,pg_signal_thread,NULL,0,NULL);
206-
if (signal_thread_handle==NULL)
207-
ereport(FATAL,
208-
(errmsg_internal("Failed to create signal handler thread!")));
209-
210-
if (!SetConsoleCtrlHandler(pg_console_handler, TRUE))
211-
ereport(FATAL,
212-
(errmsg_internal("Failed to set console control handler!")));
213-
}
214-
215-
216-
/* Dispatch all signals currently queued and not blocked
217-
* Blocked signals are ignored, and will be fired at the time of
218-
* the sigsetmask() call. */
219-
staticvoid
220-
dispatch_queued_signals(void)
221-
{
222-
inti;
223-
224-
EnterCriticalSection(&pg_signal_crit_sec);
225-
while (pg_signal_queue& ~pg_signal_mask)
226-
{
227-
/* One or more unblocked signals queued for execution */
228-
229-
intexec_mask=pg_signal_queue& ~pg_signal_mask;
230-
231-
for (i=0;i<PG_SIGNAL_COUNT;i++)
232-
{
233-
if (exec_mask&sigmask(i))
234-
{
235-
/* Execute this signal */
236-
pqsigfuncsig=pg_signal_array[i];
237-
238-
if (sig==SIG_DFL)
239-
sig=pg_signal_defaults[i];
240-
pg_signal_queue &= ~sigmask(i);
241-
if (sig!=SIG_ERR&&sig!=SIG_IGN&&sig!=SIG_DFL)
242-
{
243-
LeaveCriticalSection(&pg_signal_crit_sec);
244-
sig(i);
245-
EnterCriticalSection(&pg_signal_crit_sec);
246-
break;/* Restart outer loop, in case signal mask
247-
* or queue has been modified inside
248-
* signal handler */
249-
}
250-
}
251-
}
252-
}
253-
LeaveCriticalSection(&pg_signal_crit_sec);
254-
}
255-
256-
/* signal masking. Only called on main thread, no sync required */
257-
int
258-
pqsigsetmask(intmask)
259-
{
260-
intprevmask;
261-
262-
prevmask=pg_signal_mask;
263-
pg_signal_mask=mask;
264-
265-
/*
266-
* Dispatch any signals queued up right away, in case we have
267-
* unblocked one or more signals previously queued
268-
*/
269-
dispatch_queued_signals();
270-
271-
returnprevmask;
272-
}
273-
274-
275-
/* signal manipulation. Only called on main thread, no sync required */
276-
pqsigfunc
277-
pqsignal(intsignum,pqsigfunchandler)
278-
{
279-
pqsigfuncprevfunc;
280-
281-
if (signum >=PG_SIGNAL_COUNT||signum<0)
282-
returnSIG_ERR;
283-
prevfunc=pg_signal_array[signum];
284-
pg_signal_array[signum]=handler;
285-
returnprevfunc;
286-
}
287-
288-
/* signal sending */
289-
int
290-
pqkill(intpid,intsig)
291-
{
292-
charpipename[128];
293-
BYTEsigData=sig;
294-
BYTEsigRet=0;
295-
DWORDbytes;
296-
297-
if (sig >=PG_SIGNAL_COUNT||sig <=0)
298-
{
299-
errno=EINVAL;
300-
return-1;
301-
}
302-
if (pid <=0)
303-
{
304-
/* No support for process groups */
305-
errno=EINVAL;
306-
return-1;
307-
}
308-
wsprintf(pipename,"\\\\.\\pipe\\pgsignal_%i",pid);
309-
if (!CallNamedPipe(pipename,&sigData,1,&sigRet,1,&bytes,1000))
310-
{
311-
if (GetLastError()==ERROR_FILE_NOT_FOUND)
312-
errno=ESRCH;
313-
elseif (GetLastError()==ERROR_ACCESS_DENIED)
314-
errno=EPERM;
315-
else
316-
errno=EINVAL;
317-
return-1;
318-
}
319-
if (bytes!=1||sigRet!=sig)
320-
{
321-
errno=ESRCH;
322-
return-1;
323-
}
324-
325-
return0;
326-
}
327-
328-
/* APC callback scheduled on main thread when signals are fired */
329-
staticvoidCALLBACK
330-
pg_signal_apc(ULONG_PTRparam)
331-
{
332-
dispatch_queued_signals();
333-
}
334-
335-
/*
336-
* All functions below execute on the signal handler thread
337-
* and must be synchronized as such!
338-
* NOTE! The only global variable that can be used is
339-
* pg_signal_queue!
340-
*/
341-
342-
343-
void
344-
pg_queue_signal(intsignum)
345-
{
346-
if (signum >=PG_SIGNAL_COUNT||signum<0)
347-
return;
348-
349-
EnterCriticalSection(&pg_signal_crit_sec);
350-
pg_signal_queue |=sigmask(signum);
351-
LeaveCriticalSection(&pg_signal_crit_sec);
352-
353-
QueueUserAPC(pg_signal_apc,pgwin32_main_thread_handle, (ULONG_PTR)NULL);
354-
}
355-
356-
/* Signal dispatching thread */
357-
staticDWORDWINAPI
358-
pg_signal_dispatch_thread(LPVOIDparam)
359-
{
360-
HANDLEpipe= (HANDLE)param;
361-
BYTEsigNum;
362-
DWORDbytes;
363-
364-
if (!ReadFile(pipe,&sigNum,1,&bytes,NULL))
365-
{
366-
/* Client died before sending */
367-
CloseHandle(pipe);
368-
return0;
369-
}
370-
if (bytes!=1)
371-
{
372-
/* Received <bytes> bytes over signal pipe (should be 1) */
373-
CloseHandle(pipe);
374-
return0;
375-
}
376-
WriteFile(pipe,&sigNum,1,&bytes,NULL);/* Don't care if it works
377-
* or not.. */
378-
FlushFileBuffers(pipe);
379-
DisconnectNamedPipe(pipe);
380-
CloseHandle(pipe);
381-
382-
pg_queue_signal(sigNum);
383-
return0;
384-
}
385-
386-
/* Signal handling thread */
387-
staticDWORDWINAPI
388-
pg_signal_thread(LPVOIDparam)
389-
{
390-
charpipename[128];
391-
HANDLEpipe=INVALID_HANDLE_VALUE;
392-
393-
wsprintf(pipename,"\\\\.\\pipe\\pgsignal_%i",GetCurrentProcessId());
394-
395-
for (;;)
396-
{
397-
BOOLfConnected;
398-
HANDLEhThread;
399-
400-
pipe=CreateNamedPipe(pipename,PIPE_ACCESS_DUPLEX,
401-
PIPE_TYPE_MESSAGE |PIPE_READMODE_MESSAGE |PIPE_WAIT,
402-
PIPE_UNLIMITED_INSTANCES,16,16,1000,NULL);
403-
if (pipe==INVALID_HANDLE_VALUE)
404-
{
405-
fprintf(stderr,gettext("Failed to create signal listener pipe: %i. Retrying.\n"), (int)GetLastError());
406-
SleepEx(500, TRUE);
407-
continue;
408-
}
409-
410-
fConnected=ConnectNamedPipe(pipe,NULL) ? TRUE : (GetLastError()==ERROR_PIPE_CONNECTED);
411-
if (fConnected)
412-
{
413-
hThread=CreateThread(NULL,0,
414-
(LPTHREAD_START_ROUTINE)pg_signal_dispatch_thread,
415-
(LPVOID)pipe,0,NULL);
416-
if (hThread==INVALID_HANDLE_VALUE)
417-
fprintf(stderr,gettext("Failed to create signal dispatch thread: %i\n"), (int)GetLastError());
418-
else
419-
CloseHandle(hThread);
420-
}
421-
else
422-
/* Connection failed. Cleanup and try again */
423-
CloseHandle(pipe);
424-
}
425-
return0;
426-
}
427-
428-
429-
/* Console control handler will execute on a thread created
430-
by the OS at the time of invocation */
431-
staticBOOLWINAPIpg_console_handler(DWORDdwCtrlType) {
432-
if (dwCtrlType==CTRL_C_EVENT||
433-
dwCtrlType==CTRL_BREAK_EVENT||
434-
dwCtrlType==CTRL_CLOSE_EVENT||
435-
dwCtrlType==CTRL_SHUTDOWN_EVENT) {
436-
pg_queue_signal(SIGINT);
437-
return TRUE;
438-
}
439-
return FALSE;
440-
}
441-
442-
443-
#endif
156+
#endif/* WIN32 */

‎src/backend/port/win32/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@
44
# Makefile for port/win32
55
#
66
# IDENTIFICATION
7-
# $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.3 2004/02/18 16:25:12 momjian Exp $
7+
# $PostgreSQL: pgsql/src/backend/port/win32/Makefile,v 1.4 2004/04/12 16:19:18 momjian Exp $
88
#
99
#-------------------------------------------------------------------------
1010

1111
subdir = src/backend/port/win32
1212
top_builddir = ../../../..
1313
include$(top_builddir)/src/Makefile.global
1414

15-
OBJS = sema.o shmem.o timer.o
15+
OBJS = sema.o shmem.o timer.o socket.o signal.o
1616

1717
all: SUBSYS.o
1818

‎src/backend/port/win32/sema.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
77
*
88
* IDENTIFICATION
9-
* $PostgreSQL: pgsql/src/backend/port/win32/sema.c,v 1.5 2004/02/1220:37:34 momjian Exp $
9+
* $PostgreSQL: pgsql/src/backend/port/win32/sema.c,v 1.6 2004/04/1216:19:18 momjian Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -228,18 +228,25 @@ semop(int semId, struct sembuf * sops, int nsops)
228228
if (sops[0].sem_op==-1)
229229
{
230230
DWORDret;
231+
HANDLEwh[2];
231232

232-
if (sops[0].sem_flg&IPC_NOWAIT)
233-
ret=WaitForSingleObject(cur_handle,0);
234-
else
235-
ret=WaitForSingleObject(cur_handle,INFINITE);
233+
wh[0]=cur_handle;
234+
wh[1]=pgwin32_signal_event;
235+
236+
ret=WaitForMultipleObjects(2,wh, FALSE, (sops[0].sem_flg&IPC_NOWAIT)?0:INFINITE);
236237

237238
if (ret==WAIT_OBJECT_0)
238239
{
239240
/* We got it! */
240241
sem_counts[sops[0].sem_num]--;
241242
return0;
242243
}
244+
elseif (ret==WAIT_OBJECT_0+1)
245+
{
246+
/* Signal event is set - we have a signal to deliver */
247+
pgwin32_dispatch_queued_signals();
248+
errno=EINTR;
249+
}
243250
elseif (ret==WAIT_TIMEOUT)
244251
/* Couldn't get it */
245252
errno=EAGAIN;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp