mirror of
https://github.com/postgres/postgres.git
synced 2025-11-12 05:01:15 +03:00
From: Tom Lane <tgl@sss.pgh.pa.us>
Making PQrequestCancel safe to call in a signal handler turned out to be
much easier than I feared. So here are the diffs.
Some notes:
* I modified the postmaster's packet "iodone" callback interface to allow
the callback routine to return a continue-or-drop-connection return
code; this was necessary to allow the connection to be closed after
receiving a Cancel, rather than proceeding to launch a new backend...
Being a neatnik, I also made the iodone proc have a typechecked
parameter list.
* I deleted all code I could find that had to do with OOB.
* I made some edits to ensure that all signals mentioned in the code
are referred to symbolically not by numbers ("SIGUSR2" not "2").
I think Bruce may have already done at least some of the same edits;
I hope that merging these patches is not too painful.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.34 1998/06/27 04:53:29 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.35 1998/07/09 03:28:44 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -21,11 +21,11 @@
|
||||
* 2.a If the process is the same as the backend process that issued
|
||||
* notification (we are notifying something that we are listening),
|
||||
* signal the corresponding frontend over the comm channel.
|
||||
* 2.b For all other listening processes, we send kill(2) to wake up
|
||||
* 2.b For all other listening processes, we send kill(SIGUSR2) to wake up
|
||||
* the listening backend.
|
||||
* 3. Upon receiving a kill(2) signal from another backend process notifying
|
||||
* that one of the relation that we are listening is being notified,
|
||||
* we can be in either of two following states:
|
||||
* 3. Upon receiving a kill(SIGUSR2) signal from another backend process
|
||||
* notifying that one of the relation that we are listening is being
|
||||
* notified, we can be in either of two following states:
|
||||
* 3.a We are sleeping, wake up and signal our frontend.
|
||||
* 3.b We are in middle of another transaction, wait until the end of
|
||||
* of the current transaction and signal our frontend.
|
||||
@@ -46,7 +46,7 @@
|
||||
* (which takes place after commit) to all listeners on this relation.
|
||||
*
|
||||
* 3. Async. notification results in all backends listening on relation
|
||||
* to be woken up, by a process signal kill(2), with name of relation
|
||||
* to be woken up, by a process signal kill(SIGUSR2), with name of relation
|
||||
* passed in shared memory.
|
||||
*
|
||||
* 4. Each backend notifies its respective frontend over the comm
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.28 1998/06/13 04:27:14 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/auth.c,v 1.29 1998/07/09 03:28:45 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -40,13 +40,13 @@
|
||||
#include <libpq/crypt.h>
|
||||
|
||||
|
||||
static void sendAuthRequest(Port *port, AuthRequest areq, void (*handler) ());
|
||||
static void handle_done_auth(Port *port);
|
||||
static void handle_krb4_auth(Port *port);
|
||||
static void handle_krb5_auth(Port *port);
|
||||
static void handle_password_auth(Port *port);
|
||||
static void readPasswordPacket(char *arg, PacketLen len, char *pkt);
|
||||
static void pg_passwordv0_recvauth(char *arg, PacketLen len, char *pkt);
|
||||
static void sendAuthRequest(Port *port, AuthRequest areq, PacketDoneProc handler);
|
||||
static int handle_done_auth(void *arg, PacketLen len, void *pkt);
|
||||
static int handle_krb4_auth(void *arg, PacketLen len, void *pkt);
|
||||
static int handle_krb5_auth(void *arg, PacketLen len, void *pkt);
|
||||
static int handle_password_auth(void *arg, PacketLen len, void *pkt);
|
||||
static int readPasswordPacket(void *arg, PacketLen len, void *pkt);
|
||||
static int pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt);
|
||||
static int checkPassword(Port *port, char *user, char *password);
|
||||
static int old_be_recvauth(Port *port);
|
||||
static int map_old_to_new(Port *port, UserAuth old, int status);
|
||||
@@ -327,8 +327,8 @@ pg_krb5_recvauth(Port *port)
|
||||
* Handle a v0 password packet.
|
||||
*/
|
||||
|
||||
static void
|
||||
pg_passwordv0_recvauth(char *arg, PacketLen len, char *pkt)
|
||||
static int
|
||||
pg_passwordv0_recvauth(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
Port *port;
|
||||
PasswordPacketV0 *pp;
|
||||
@@ -393,6 +393,8 @@ pg_passwordv0_recvauth(char *arg, PacketLen len, char *pkt)
|
||||
if (map_old_to_new(port, uaPassword, status) != STATUS_OK)
|
||||
auth_failed(port);
|
||||
}
|
||||
|
||||
return (STATUS_OK); /* don't close the connection yet */
|
||||
}
|
||||
|
||||
|
||||
@@ -433,7 +435,7 @@ be_recvauth(Port *port)
|
||||
else
|
||||
{
|
||||
AuthRequest areq;
|
||||
void (*auth_handler) ();
|
||||
PacketDoneProc auth_handler;
|
||||
|
||||
/* Keep the compiler quiet. */
|
||||
|
||||
@@ -499,7 +501,7 @@ be_recvauth(Port *port)
|
||||
*/
|
||||
|
||||
static void
|
||||
sendAuthRequest(Port *port, AuthRequest areq, void (*handler) ())
|
||||
sendAuthRequest(Port *port, AuthRequest areq, PacketDoneProc handler)
|
||||
{
|
||||
char *dp,
|
||||
*sp;
|
||||
@@ -527,7 +529,7 @@ sendAuthRequest(Port *port, AuthRequest areq, void (*handler) ())
|
||||
i += 2;
|
||||
}
|
||||
|
||||
PacketSendSetup(&port->pktInfo, i, handler, (char *) port);
|
||||
PacketSendSetup(&port->pktInfo, i, handler, (void *) port);
|
||||
}
|
||||
|
||||
|
||||
@@ -535,8 +537,8 @@ sendAuthRequest(Port *port, AuthRequest areq, void (*handler) ())
|
||||
* Called when we have told the front end that it is authorised.
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_done_auth(Port *port)
|
||||
static int
|
||||
handle_done_auth(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
|
||||
/*
|
||||
@@ -544,7 +546,7 @@ handle_done_auth(Port *port)
|
||||
* start.
|
||||
*/
|
||||
|
||||
return;
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -553,13 +555,17 @@ handle_done_auth(Port *port)
|
||||
* authentication.
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_krb4_auth(Port *port)
|
||||
static int
|
||||
handle_krb4_auth(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
Port *port = (Port *) arg;
|
||||
|
||||
if (pg_krb4_recvauth(port) != STATUS_OK)
|
||||
auth_failed(port);
|
||||
else
|
||||
sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -568,13 +574,17 @@ handle_krb4_auth(Port *port)
|
||||
* authentication.
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_krb5_auth(Port *port)
|
||||
static int
|
||||
handle_krb5_auth(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
Port *port = (Port *) arg;
|
||||
|
||||
if (pg_krb5_recvauth(port) != STATUS_OK)
|
||||
auth_failed(port);
|
||||
else
|
||||
sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -583,12 +593,16 @@ handle_krb5_auth(Port *port)
|
||||
* authentication.
|
||||
*/
|
||||
|
||||
static void
|
||||
handle_password_auth(Port *port)
|
||||
static int
|
||||
handle_password_auth(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
Port *port = (Port *) arg;
|
||||
|
||||
/* Set up the read of the password packet. */
|
||||
|
||||
PacketReceiveSetup(&port->pktInfo, readPasswordPacket, (char *) port);
|
||||
PacketReceiveSetup(&port->pktInfo, readPasswordPacket, (void *) port);
|
||||
|
||||
return STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -596,13 +610,11 @@ handle_password_auth(Port *port)
|
||||
* Called when we have received the password packet.
|
||||
*/
|
||||
|
||||
static void
|
||||
readPasswordPacket(char *arg, PacketLen len, char *pkt)
|
||||
static int
|
||||
readPasswordPacket(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
char password[sizeof(PasswordPacket) + 1];
|
||||
Port *port;
|
||||
|
||||
port = (Port *) arg;
|
||||
Port *port = (Port *) arg;
|
||||
|
||||
/* Silently truncate a password that is too big. */
|
||||
|
||||
@@ -615,6 +627,8 @@ readPasswordPacket(char *arg, PacketLen len, char *pkt)
|
||||
auth_failed(port);
|
||||
else
|
||||
sendAuthRequest(port, AUTH_REQ_OK, handle_done_auth);
|
||||
|
||||
return (STATUS_OK); /* don't close the connection yet */
|
||||
}
|
||||
|
||||
|
||||
@@ -662,7 +676,7 @@ old_be_recvauth(Port *port)
|
||||
|
||||
case STARTUP_PASSWORD_MSG:
|
||||
PacketReceiveSetup(&port->pktInfo, pg_passwordv0_recvauth,
|
||||
(char *) port);
|
||||
(void *) port);
|
||||
|
||||
return STATUS_OK;
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.47 1998/06/27 04:53:30 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/pqcomm.c,v 1.48 1998/07/09 03:28:46 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -30,7 +30,6 @@
|
||||
* pq_getinserv - initialize address from host and service name
|
||||
* pq_connect - create remote input / output connection
|
||||
* pq_accept - accept remote input / output connection
|
||||
* pq_async_notify - receive notification from backend.
|
||||
*
|
||||
* NOTES
|
||||
* These functions are used by both frontend applications and
|
||||
@@ -79,7 +78,6 @@
|
||||
FILE *Pfout,
|
||||
*Pfin;
|
||||
FILE *Pfdebug; /* debugging libpq */
|
||||
int PQAsyncNotifyWaiting; /* for async. notification */
|
||||
|
||||
/* --------------------------------
|
||||
* pq_init - open portal file descriptors
|
||||
@@ -160,9 +158,7 @@ pq_close()
|
||||
fclose(Pfout);
|
||||
Pfout = NULL;
|
||||
}
|
||||
PQAsyncNotifyWaiting = 0;
|
||||
PQnotifies_init();
|
||||
pq_unregoob();
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
@@ -418,29 +414,6 @@ pq_putint(int i, int b)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---
|
||||
* pq_sendoob - send a string over the out-of-band channel
|
||||
* pq_recvoob - receive a string over the oob channel
|
||||
* NB: Fortunately, the out-of-band channel doesn't conflict with
|
||||
* buffered I/O because it is separate from regular com. channel.
|
||||
* ---
|
||||
*/
|
||||
int
|
||||
pq_sendoob(char *msg, int len)
|
||||
{
|
||||
int fd = fileno(Pfout);
|
||||
|
||||
return send(fd, msg, len, MSG_OOB);
|
||||
}
|
||||
|
||||
int
|
||||
pq_recvoob(char *msgPtr, int len)
|
||||
{
|
||||
int fd = fileno(Pfout);
|
||||
|
||||
return recv(fd, msgPtr, len, MSG_OOB);
|
||||
}
|
||||
|
||||
/* --------------------------------
|
||||
* pq_getinaddr - initialize address from host and port number
|
||||
* --------------------------------
|
||||
@@ -507,55 +480,6 @@ pq_getinserv(struct sockaddr_in * sin, char *host, char *serv)
|
||||
return (pq_getinaddr(sin, host, ntohs(ss->s_port)));
|
||||
}
|
||||
|
||||
/*
|
||||
* register an out-of-band listener proc--at most one allowed.
|
||||
* This is used for receiving async. notification from the backend.
|
||||
*/
|
||||
void
|
||||
pq_regoob(void (*fptr) ())
|
||||
{
|
||||
int fd = fileno(Pfout);
|
||||
|
||||
#if defined(hpux)
|
||||
ioctl(fd, FIOSSAIOOWN, MyProcPid);
|
||||
#elif defined(sco)
|
||||
ioctl(fd, SIOCSPGRP, MyProcPid);
|
||||
#else
|
||||
fcntl(fd, F_SETOWN, MyProcPid);
|
||||
#endif /* hpux */
|
||||
pqsignal(SIGURG, fptr);
|
||||
}
|
||||
|
||||
void
|
||||
pq_unregoob()
|
||||
{
|
||||
pqsignal(SIGURG, SIG_DFL);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
pq_async_notify()
|
||||
{
|
||||
char msg[20];
|
||||
|
||||
/* int len = sizeof(msg); */
|
||||
int len = 20;
|
||||
|
||||
if (pq_recvoob(msg, len) >= 0)
|
||||
{
|
||||
/* debugging */
|
||||
printf("received notification: %s\n", msg);
|
||||
PQAsyncNotifyWaiting = 1;
|
||||
/* PQappendNotify(msg+1); */
|
||||
}
|
||||
else
|
||||
{
|
||||
extern int errno;
|
||||
|
||||
printf("SIGURG but no data: len = %d, err=%d\n", len, errno);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Streams -- wrapper around Unix socket system calls
|
||||
*
|
||||
@@ -620,7 +544,7 @@ StreamServerPort(char *hostName, short portName, int *fdP)
|
||||
pqdebug("%s", PQerrormsg);
|
||||
return (STATUS_ERROR);
|
||||
}
|
||||
bzero(&saddr, sizeof(saddr));
|
||||
MemSet((char *) &saddr, 0, sizeof(saddr));
|
||||
saddr.sa.sa_family = family;
|
||||
if (family == AF_UNIX)
|
||||
{
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.15 1998/02/26 04:31:56 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/libpq/Attic/pqpacket.c,v 1.16 1998/07/09 03:28:46 scrappy Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -33,7 +33,7 @@
|
||||
* Set up a packet read for the postmaster event loop.
|
||||
*/
|
||||
|
||||
void PacketReceiveSetup(Packet *pkt, void (*iodone) (), char *arg)
|
||||
void PacketReceiveSetup(Packet *pkt, PacketDoneProc iodone, void *arg)
|
||||
{
|
||||
pkt->nrtodo = sizeof(pkt->len);
|
||||
pkt->ptr = (char *) &pkt->len;
|
||||
@@ -94,8 +94,8 @@ PacketReceiveFragment(Packet *pkt, int sock)
|
||||
if (pkt->iodone == NULL)
|
||||
return STATUS_ERROR;
|
||||
|
||||
(*pkt->iodone) (pkt->arg, pkt->len - sizeof(pkt->len),
|
||||
(char *) &pkt->pkt);
|
||||
return (*pkt->iodone) (pkt->arg, pkt->len - sizeof(pkt->len),
|
||||
(void *) &pkt->pkt);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
@@ -107,7 +107,7 @@ PacketReceiveFragment(Packet *pkt, int sock)
|
||||
if (errno == EINTR)
|
||||
return STATUS_OK;
|
||||
|
||||
fprintf(stderr, "read() system call failed\n");
|
||||
perror("PacketReceiveFragment: read() failed");
|
||||
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
@@ -117,8 +117,9 @@ PacketReceiveFragment(Packet *pkt, int sock)
|
||||
* Set up a packet write for the postmaster event loop.
|
||||
*/
|
||||
|
||||
void PacketSendSetup(Packet *pkt, int nbytes, void (*iodone) (), char *arg)
|
||||
void PacketSendSetup(Packet *pkt, int nbytes, PacketDoneProc iodone, void *arg)
|
||||
{
|
||||
pkt->len = (PacketLen) nbytes;
|
||||
pkt->nrtodo = nbytes;
|
||||
pkt->ptr = (char *) &pkt->pkt;
|
||||
pkt->iodone = iodone;
|
||||
@@ -153,7 +154,8 @@ PacketSendFragment(Packet *pkt, int sock)
|
||||
if (pkt->iodone == NULL)
|
||||
return STATUS_ERROR;
|
||||
|
||||
(*pkt->iodone) (pkt->arg);
|
||||
return (*pkt->iodone) (pkt->arg, pkt->len,
|
||||
(void *) &pkt->pkt);
|
||||
}
|
||||
|
||||
return STATUS_OK;
|
||||
@@ -165,7 +167,7 @@ PacketSendFragment(Packet *pkt, int sock)
|
||||
if (errno == EINTR)
|
||||
return STATUS_OK;
|
||||
|
||||
fprintf(stderr, "write() system call failed\n");
|
||||
perror("PacketSendFragment: write() failed");
|
||||
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.92 1998/06/27 14:06:40 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.93 1998/07/09 03:28:47 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
*
|
||||
@@ -206,7 +206,6 @@ static int orgsigmask = sigblock(0);
|
||||
*/
|
||||
|
||||
static unsigned int random_seed = 0;
|
||||
long MyCancelKey = 0;
|
||||
|
||||
extern char *optarg;
|
||||
extern int optind,
|
||||
@@ -228,7 +227,8 @@ static void ExitPostmaster(int status);
|
||||
static void usage(const char *);
|
||||
static int ServerLoop(void);
|
||||
static int BackendStartup(Port *port);
|
||||
static void readStartupPacket(char *arg, PacketLen len, char *pkt);
|
||||
static int readStartupPacket(void *arg, PacketLen len, void *pkt);
|
||||
static int processCancelRequest(Port *port, PacketLen len, void *pkt);
|
||||
static int initMasks(fd_set *rmask, fd_set *wmask);
|
||||
static long PostmasterRandom(void);
|
||||
static void RandomSalt(char *salt);
|
||||
@@ -518,6 +518,10 @@ PostmasterMain(int argc, char *argv[])
|
||||
if (silentflag)
|
||||
pmdaemonize();
|
||||
|
||||
/*
|
||||
* Set up signal handlers for the postmaster process.
|
||||
*/
|
||||
|
||||
pqsignal(SIGINT, pmdie);
|
||||
pqsignal(SIGCHLD, reaper);
|
||||
pqsignal(SIGTTIN, SIG_IGN);
|
||||
@@ -657,14 +661,14 @@ ServerLoop(void)
|
||||
(port = ConnCreate(ServerSock_UNIX)) != NULL)
|
||||
PacketReceiveSetup(&port->pktInfo,
|
||||
readStartupPacket,
|
||||
(char *) port);
|
||||
(void *) port);
|
||||
|
||||
if (ServerSock_INET != INVALID_SOCK &&
|
||||
FD_ISSET(ServerSock_INET, &rmask) &&
|
||||
(port = ConnCreate(ServerSock_INET)) != NULL)
|
||||
PacketReceiveSetup(&port->pktInfo,
|
||||
readStartupPacket,
|
||||
(char *) port);
|
||||
(void *) port);
|
||||
|
||||
/* Build up new masks for select(). */
|
||||
|
||||
@@ -790,8 +794,8 @@ initMasks(fd_set *rmask, fd_set *wmask)
|
||||
* Called when the startup packet has been read.
|
||||
*/
|
||||
|
||||
static void
|
||||
readStartupPacket(char *arg, PacketLen len, char *pkt)
|
||||
static int
|
||||
readStartupPacket(void *arg, PacketLen len, void *pkt)
|
||||
{
|
||||
Port *port;
|
||||
StartupPacket *si;
|
||||
@@ -799,6 +803,28 @@ readStartupPacket(char *arg, PacketLen len, char *pkt)
|
||||
port = (Port *) arg;
|
||||
si = (StartupPacket *) pkt;
|
||||
|
||||
/* The first field is either a protocol version number or
|
||||
* a special request code.
|
||||
*/
|
||||
|
||||
port->proto = ntohl(si->protoVersion);
|
||||
|
||||
if (port->proto == CANCEL_REQUEST_CODE)
|
||||
return processCancelRequest(port, len, pkt);
|
||||
|
||||
/* Could add additional special packet types here */
|
||||
|
||||
/* Check we can handle the protocol the frontend is using. */
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
|
||||
PG_PROTOCOL_MAJOR(port->proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
|
||||
(PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
|
||||
PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
|
||||
{
|
||||
PacketSendError(&port->pktInfo, "Unsupported frontend protocol.");
|
||||
return STATUS_OK; /* don't close the connection yet */
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the parameters from the startup packet as C strings. The
|
||||
* packet destination was cleared first so a short packet has zeros
|
||||
@@ -815,31 +841,74 @@ readStartupPacket(char *arg, PacketLen len, char *pkt)
|
||||
if (port->database[0] == '\0')
|
||||
StrNCpy(port->database, si->user, sizeof(port->database) - 1);
|
||||
|
||||
/* Check we can handle the protocol the frontend is using. */
|
||||
|
||||
port->proto = ntohl(si->protoVersion);
|
||||
|
||||
if (PG_PROTOCOL_MAJOR(port->proto) < PG_PROTOCOL_MAJOR(PG_PROTOCOL_EARLIEST) ||
|
||||
PG_PROTOCOL_MAJOR(port->proto) > PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) ||
|
||||
(PG_PROTOCOL_MAJOR(port->proto) == PG_PROTOCOL_MAJOR(PG_PROTOCOL_LATEST) &&
|
||||
PG_PROTOCOL_MINOR(port->proto) > PG_PROTOCOL_MINOR(PG_PROTOCOL_LATEST)))
|
||||
{
|
||||
PacketSendError(&port->pktInfo, "Unsupported frontend protocol.");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check a user name was given. */
|
||||
|
||||
if (port->user[0] == '\0')
|
||||
{
|
||||
PacketSendError(&port->pktInfo,
|
||||
"No Postgres username specified in startup packet.");
|
||||
return;
|
||||
return STATUS_OK; /* don't close the connection yet */
|
||||
}
|
||||
|
||||
/* Start the authentication itself. */
|
||||
|
||||
be_recvauth(port);
|
||||
|
||||
return STATUS_OK; /* don't close the connection yet */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The client has sent a cancel request packet, not a normal
|
||||
* start-a-new-backend packet. Perform the necessary processing.
|
||||
* Note that in any case, we return STATUS_ERROR to close the
|
||||
* connection immediately. Nothing is sent back to the client.
|
||||
*/
|
||||
|
||||
static int
|
||||
processCancelRequest(Port *port, PacketLen len, void *pkt)
|
||||
{
|
||||
CancelRequestPacket *canc = (CancelRequestPacket *) pkt;
|
||||
int backendPID;
|
||||
long cancelAuthCode;
|
||||
Dlelem *curr;
|
||||
Backend *bp;
|
||||
|
||||
backendPID = (int) ntohl(canc->backendPID);
|
||||
cancelAuthCode = (long) ntohl(canc->cancelAuthCode);
|
||||
|
||||
/* See if we have a matching backend */
|
||||
|
||||
for (curr = DLGetHead(BackendList); curr; curr = DLGetSucc(curr))
|
||||
{
|
||||
bp = (Backend *) DLE_VAL(curr);
|
||||
if (bp->pid == backendPID)
|
||||
{
|
||||
if (bp->cancel_key == cancelAuthCode)
|
||||
{
|
||||
/* Found a match; signal that backend to cancel current op */
|
||||
if (DebugLvl)
|
||||
fprintf(stderr, "%s: processCancelRequest: sending SIGINT to process %d\n",
|
||||
progname, bp->pid);
|
||||
kill(bp->pid, SIGINT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Right PID, wrong key: no way, Jose */
|
||||
if (DebugLvl)
|
||||
fprintf(stderr, "%s: processCancelRequest: bad key in cancel request for process %d\n",
|
||||
progname, bp->pid);
|
||||
}
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* No matching backend */
|
||||
if (DebugLvl)
|
||||
fprintf(stderr, "%s: processCancelRequest: bad PID in cancel request for process %d\n",
|
||||
progname, backendPID);
|
||||
|
||||
return STATUS_ERROR;
|
||||
}
|
||||
|
||||
|
||||
@@ -1221,6 +1290,8 @@ DoBackend(Port *port)
|
||||
char dbbuf[ARGV_SIZE + 1];
|
||||
int ac = 0;
|
||||
int i;
|
||||
struct timeval now;
|
||||
struct timezone tz;
|
||||
|
||||
/*
|
||||
* Let's clean up ourselves as the postmaster child
|
||||
@@ -1254,7 +1325,16 @@ DoBackend(Port *port)
|
||||
if (NetServer)
|
||||
StreamClose(ServerSock_INET);
|
||||
StreamClose(ServerSock_UNIX);
|
||||
|
||||
|
||||
/*
|
||||
* Don't want backend to be able to see the postmaster random number
|
||||
* generator state. We have to clobber the static random_seed *and*
|
||||
* start a new random sequence in the random() library function.
|
||||
*/
|
||||
random_seed = 0;
|
||||
gettimeofday(&now, &tz);
|
||||
srandom(now.tv_usec);
|
||||
|
||||
/* Now, on to standard postgres stuff */
|
||||
|
||||
MyProcPid = getpid();
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.78 1998/06/27 04:53:43 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.79 1998/07/09 03:28:48 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
* this is the "main" module of the postgres backend and
|
||||
@@ -724,7 +724,7 @@ pg_exec_query_dest(char *query_string, /* string to execute */
|
||||
/* --------------------------------
|
||||
* signal handler routines used in PostgresMain()
|
||||
*
|
||||
* handle_warn() is used to catch kill(getpid(),1) which
|
||||
* handle_warn() is used to catch kill(getpid(), SIGHUP) which
|
||||
* occurs when elog(ERROR) is called.
|
||||
*
|
||||
* quickdie() occurs when signalled by the postmaster.
|
||||
@@ -777,7 +777,7 @@ FloatExceptionHandler(SIGNAL_ARGS)
|
||||
}
|
||||
|
||||
|
||||
/* signal handler for query cancel */
|
||||
/* signal handler for query cancel signal from postmaster */
|
||||
static void
|
||||
QueryCancelHandler(SIGNAL_ARGS)
|
||||
{
|
||||
@@ -787,12 +787,9 @@ QueryCancelHandler(SIGNAL_ARGS)
|
||||
void
|
||||
CancelQuery(void)
|
||||
{
|
||||
char dummy;
|
||||
|
||||
/* throw it away */
|
||||
while (pq_recvoob(&dummy, 1) > 0)
|
||||
;
|
||||
/* QueryCancel reset in longjump after elog() call */
|
||||
/* QueryCancel flag will be reset in main loop, which we reach by
|
||||
* longjmp from elog().
|
||||
*/
|
||||
elog(ERROR, "Query was cancelled.");
|
||||
}
|
||||
|
||||
@@ -1261,7 +1258,6 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
}
|
||||
pq_init(Portfd);
|
||||
whereToSendOutput = Remote;
|
||||
pq_regoob(QueryCancelHandler); /* we do it here so the backend it connected */
|
||||
}
|
||||
else
|
||||
whereToSendOutput = Debug;
|
||||
@@ -1287,6 +1283,24 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ----------------
|
||||
* Set up handler for cancel-request signal, and
|
||||
* send this backend's cancellation info to the frontend.
|
||||
* This should not be done until we are sure startup is successful.
|
||||
* ----------------
|
||||
*/
|
||||
|
||||
pqsignal(SIGINT, QueryCancelHandler);
|
||||
|
||||
if (whereToSendOutput == Remote &&
|
||||
PG_PROTOCOL_MAJOR(FrontendProtocol) >= 2)
|
||||
{
|
||||
pq_putnchar("K", 1);
|
||||
pq_putint((int32) MyProcPid, sizeof(int32));
|
||||
pq_putint((int32) MyCancelKey, sizeof(int32));
|
||||
/* Need not flush since ReadyForQuery will do it. */
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
* if an exception is encountered, processing resumes here
|
||||
* so we abort the current transaction and start a new one.
|
||||
@@ -1294,7 +1308,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
* so that the slaves signal the master to abort the transaction
|
||||
* rather than calling AbortCurrentTransaction() themselves.
|
||||
*
|
||||
* Note: elog(ERROR) causes a kill(getpid(),1) to occur sending
|
||||
* Note: elog(ERROR) causes a kill(getpid(), SIGHUP) to occur sending
|
||||
* us back here.
|
||||
* ----------------
|
||||
*/
|
||||
@@ -1325,7 +1339,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
if (!IsUnderPostmaster)
|
||||
{
|
||||
puts("\nPOSTGRES backend interactive interface");
|
||||
puts("$Revision: 1.78 $ $Date: 1998/06/27 04:53:43 $");
|
||||
puts("$Revision: 1.79 $ $Date: 1998/07/09 03:28:48 $");
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
@@ -1431,7 +1445,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[])
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(ERROR, "unknown frontend message was recieved");
|
||||
elog(ERROR, "unknown frontend message was received");
|
||||
}
|
||||
|
||||
/* ----------------
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.23 1998/05/29 17:00:18 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/utils/init/globals.c,v 1.24 1998/07/09 03:28:51 scrappy Exp $
|
||||
*
|
||||
* NOTES
|
||||
* Globals used all over the place should be declared here and not
|
||||
@@ -44,6 +44,8 @@ bool QueryCancel = false;
|
||||
|
||||
int MyProcPid;
|
||||
|
||||
long MyCancelKey;
|
||||
|
||||
char *DataDir;
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user