]> git.8kb.co.uk Git - pgpool-ii/pgpool-ii_2.2.5/blob - pool_sema.c
Attempt to send a proper failure message to frontend when authentication
[pgpool-ii/pgpool-ii_2.2.5] / pool_sema.c
1 /* -*-pgsql-c-*- */
2 /*
3  * $Header: /cvsroot/pgpool/pgpool-II/pool_sema.c,v 1.5.2.2 2009/08/22 04:19:49 t-ishii Exp $
4  *
5  * pgpool: a language independent connection pool server for PostgreSQL
6  * written by Tatsuo Ishii
7  *
8  * Portions Copyright (c) 2003-2009, PgPool Global Development Group
9  * Portions Copyright (c) 2003-2004, PostgreSQL Global Development Group
10  *
11  * Permission to use, copy, modify, and distribute this software and
12  * its documentation for any purpose and without fee is hereby
13  * granted, provided that the above copyright notice appear in all
14  * copies and that both that copyright notice and this permission
15  * notice appear in supporting documentation, and that the name of the
16  * author not be used in advertising or publicity pertaining to
17  * distribution of the software without specific, written prior
18  * permission. The author makes no representations about the
19  * suitability of this software for any purpose.  It is provided "as
20  * is" without express or implied warranty.
21  *
22  */
23 #include "pool.h"
24
25 #include <errno.h>
26 #include <string.h>
27 #include <sys/sem.h>
28
29 #include "pool_ipc.h"
30
31
32 #ifndef HAVE_UNION_SEMUN
33 union semun
34 {
35         int                     val;
36         struct semid_ds *buf;
37         unsigned short *array;
38 };
39 #endif
40
41
42 static int      semId;
43
44
45 /*
46  * Removes a semaphore set.
47  */
48 static void
49 IpcSemaphoreKill(int status, Datum semId)
50 {
51         union semun semun;
52         struct semid_ds seminfo;
53
54         /*
55          * Is a previously-existing sema segment still existing and in use?
56          */
57         semun.buf = &seminfo;
58         if (semctl(semId, 0, IPC_STAT, semun) < 0
59                 && (errno == EINVAL || errno == EACCES
60 #ifdef EIDRM
61                         || errno == EIDRM
62 #endif
63                 ))
64                 return;
65
66         semun.val = 0;                          /* unused, but keep compiler quiet */
67
68         if (semctl(semId, 0, IPC_RMID) < 0)
69                 pool_log("semctl(%lu, 0, IPC_RMID, ...) failed: %s", semId, strerror(errno));
70 }
71
72 /*
73  * Create a semaphore set and initialize.
74  */
75 int
76 pool_semaphore_create(int numSems)
77 {
78         int                     i;
79
80         /* Try to create new semaphore set */
81         semId = semget(IPC_PRIVATE, numSems, IPC_CREAT | IPC_EXCL | IPCProtection);
82
83         if (semId < 0)
84         {
85                 pool_error("could not create %d semaphores: %s", numSems, strerror(errno));
86                 return -1;
87         }
88
89         on_shmem_exit(IpcSemaphoreKill, semId);
90
91         /* Initialize it to count 1 */
92         for (i = 0; i < numSems; i++)
93         {
94                 union semun semun;
95
96                 semun.val = 1;
97                 if (semctl(semId, i, SETVAL, semun) < 0)
98                 {
99                         pool_error("semctl(%d, %d, SETVAL, %d) failed: %s",
100                                            semId, i, 1, strerror(errno));
101                         return -1;
102                 }
103         }
104
105         return 0;
106 }
107
108 /*
109  * Lock a semaphore (decrement count), blocking if count would be < 0
110  */
111 void
112 pool_semaphore_lock(int semNum)
113 {
114         int                     errStatus;
115         struct sembuf sops;
116
117         sops.sem_op = -1;                       /* decrement */
118         sops.sem_flg = 0;
119         sops.sem_num = semNum;
120
121         /*
122          * Note: if errStatus is -1 and errno == EINTR then it means we returned
123          * from the operation prematurely because we were sent a signal.  So we
124          * try and lock the semaphore again.
125          */
126         do
127         {
128                 errStatus = semop(semId, &sops, 1);
129         } while (errStatus < 0 && errno == EINTR);
130
131         if (errStatus < 0)
132                 pool_error("semop(id=%d) failed: %s", semId, strerror(errno));
133 }
134
135 /*
136  * Unlock a semaphore (increment count)
137  */
138 void
139 pool_semaphore_unlock(int semNum)
140 {
141         int                     errStatus;
142         struct sembuf sops;
143
144         sops.sem_op = 1;                        /* increment */
145         sops.sem_flg = 0;
146         sops.sem_num = semNum;
147
148         /*
149          * Note: if errStatus is -1 and errno == EINTR then it means we returned
150          * from the operation prematurely because we were sent a signal.  So we
151          * try and unlock the semaphore again. Not clear this can really happen,
152          * but might as well cope.
153          */
154         do
155         {
156                 errStatus = semop(semId, &sops, 1);
157         } while (errStatus < 0 && errno == EINTR);
158
159         if (errStatus < 0)
160                 pool_error("semop(id=%d) failed: %s", semId, strerror(errno));
161 }