Browse Source

Replacing old sysV sem by new POSIX solves #25

Creating new files to handle IPC stuffs : include/ipc.h src/ipc.c
Yann Weber 5 years ago
parent
commit
4daea42c44
10 changed files with 395 additions and 80 deletions
  1. 2
    1
      configure.ac
  2. 35
    10
      include/conf.h
  3. 88
    0
      include/ipc.h
  4. 1
    1
      include/pyutils.h
  5. 8
    5
      include/responder.h
  6. 2
    2
      src/Makefile.am
  7. 162
    0
      src/ipc.c
  8. 3
    0
      src/main.c
  9. 12
    18
      src/pyworker.c
  10. 82
    43
      src/responder.c

+ 2
- 1
configure.ac View File

@@ -52,6 +52,7 @@ AC_C_INLINE
52 52
 # Checks for libraries.
53 53
 AC_CHECK_LIB([fcgi], [FCGI_Accept])
54 54
 AC_CHECK_LIB([rt], [timer_create])
55
+AC_CHECK_LIB([pthread], [sem_open shm_open])
55 56
 PKG_CHECK_MODULES([CHECK], [check >= 0.9.4])
56 57
 
57 58
 # Checks for header files.
@@ -65,7 +66,7 @@ AC_TYPE_SIZE_T
65 66
 AC_FUNC_FORK
66 67
 AC_FUNC_MALLOC
67 68
 AC_FUNC_REALLOC
68
-AC_CHECK_FUNCS([bzero getcwd gettimeofday memmove strdup strerror strndup semop clone get_current_dir_name timer_settime])
69
+AC_CHECK_FUNCS([bzero getcwd gettimeofday memmove strdup strerror strndup get_current_dir_name timer_settime])
69 70
 
70 71
 AM_INIT_AUTOMAKE
71 72
 AC_CONFIG_FILES([Makefile

+ 35
- 10
include/conf.h View File

@@ -29,6 +29,7 @@
29 29
 #include <unistd.h>
30 30
 #include <getopt.h>
31 31
 #include <limits.h>
32
+#include <semaphore.h>
32 33
 #include <sys/types.h>
33 34
 #include <sys/wait.h>
34 35
 
@@ -39,8 +40,22 @@
39 40
  * @see struct_pyfcgi_conf_s
40 41
  * @ingroup conf_internal */
41 42
 
43
+/**@brief Friendly name for @ref struct pyfcgi_conf_s
44
+ * @see struct pyfcgi_conf_s */
45
+typedef struct pyfcgi_conf_s pyfcgi_conf_t;
46
+typedef struct pyfcgi_conf_logger_s pyfcgi_conf_logger_t;
47
+typedef struct pyfcgi_context_s pyfcgi_context_t;
48
+typedef struct pyfcgi_semdata_s pyfcgi_semdata_t;
49
+
50
+/**@brief Configuration globals, inherited from parent to childs
51
+ * @ingroup conf_internal
52
+ */
53
+pyfcgi_conf_t PyFCGI_conf;
54
+
55
+/* Include other PyFCGI stuff */
42 56
 #include "logger.h"
43 57
 #include "pyutils.h"
58
+#include "ipc.h"
44 59
 
45 60
 /**@defgroup ret_status Function & process return status
46 61
  */
@@ -117,11 +132,14 @@ abbreviated to one character.\n"
117 132
 
118 133
 #define PYENTRY_DEFAULT_FUN "application"
119 134
 
120
-/**@brief Friendly name for @ref struct pyfcgi_conf_s
121
- * @see struct pyfcgi_conf_s */
122
-typedef struct pyfcgi_conf_s pyfcgi_conf_t;
123
-typedef struct pyfcgi_conf_logger_s pyfcgi_conf_logger_t;
124
-typedef struct pyfcgi_context_s pyfcgi_context_t;
135
+/**@brief Stores a semaphore name and pointer */
136
+struct pyfcgi_semdata_s {
137
+	/**@brief Semaphore names. Set by master process */
138
+	char name[NAME_MAX - 4];
139
+	/**@brief Semaphore pointer. */
140
+	sem_t *sem;
141
+};
142
+
125 143
 
126 144
 /**@brief Stores contextual informations about current process */
127 145
 struct pyfcgi_context_s {
@@ -147,8 +165,8 @@ struct pyfcgi_context_s {
147 165
 	/**@brief workers count */
148 166
 	unsigned int n_wrk;
149 167
 
150
-	/**@brief semid for worker<->pool semaphore */
151
-	int semid;
168
+	/**@brief Stores IPC flag used in init */
169
+	pyfcgi_ipc_flag_t ipc_flag;
152 170
 
153 171
 	/**@brief Stores python_path (not dupped by python) */
154 172
 	wchar_t python_path[PATH_MAX];
@@ -213,11 +231,18 @@ struct pyfcgi_conf_s
213 231
 
214 232
 	/**@brief Context informations */
215 233
 	pyfcgi_context_t context;
216
-};
217 234
 
235
+	/**@brief Semaphores informations
236
+	 *
237
+	 * - sems[0] is the worker state indicator : when a worker is idle the
238
+	 * sem is incremented
239
+	 * - sems[1] is the request counter sem : when a request is handled
240
+	 * this sem is incremented
241
+	 * - sems[2] is the stats/status SHM semaphore
242
+	 */
243
+	pyfcgi_semdata_t sems[PYFCGI_NSEM];
244
+};
218 245
 
219
-/**@brief Configuration globals, inherited from parent to childs */
220
-pyfcgi_conf_t PyFCGI_conf;
221 246
 
222 247
 /**@brief Print usage on FD 2 (stdout) */
223 248
 void usage();

+ 88
- 0
include/ipc.h View File

@@ -0,0 +1,88 @@
1
+/*
2
+ * Copyright (C) 2019 Weber Yann
3
+ * 
4
+ * This file is part of PyFCGI.
5
+ * 
6
+ * PyFCGI is free software: you can redistribute it and/or modify
7
+ * it under the terms of the GNU Affero General Public License as published by
8
+ * the Free Software Foundation, either version 3 of the License, or
9
+ * any later version.
10
+ * 
11
+ * PyFCGI is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
+ * GNU Affero General Public License for more details.
15
+ * 
16
+ * You should have received a copy of the GNU Affero General Public License
17
+ * along with PyFCGI.  If not, see <http://www.gnu.org/licenses/>.
18
+ */
19
+/**@defgroup IPC Inter process communication mechanism
20
+ */
21
+/**@file ipc.h
22
+ * @ingroup IPC */
23
+#ifndef __IPC_H___
24
+#define __IPC_H___
25
+
26
+#include <fcgiapp.h>
27
+#include <fcgi_stdio.h> /* fcgi library; put it first*/
28
+
29
+#include <fcntl.h>
30
+#include <semaphore.h>
31
+#include <sys/stat.h>
32
+
33
+/**@brief Format for sem and shm */
34
+#define PYFCGI_IPCNAME_FMT "/PyFCGI-%d_%s"
35
+/**@brief Number of semaphores */
36
+#define PYFCGI_NSEM 3
37
+
38
+#define SEM_WSTATE 0
39
+#define SEM_WREQS 1
40
+#define SEM_STATS 2
41
+/**@brief Semaphore uniq name */
42
+#define PYFCGI_SEMNAMES {"WState", "WReqs", "SHMStats"}
43
+
44
+#define PyFCGI_SEM(i) (PyFCGI_conf.sems[i])
45
+
46
+/**@defgroup IPC_flags IPC component flags
47
+ * @ingroup IPC
48
+ * @brief For IPC component selection */
49
+/**@brief Worker state semaphore
50
+ * @ingroup IPC_flags */
51
+#define IPC_WSTATE 2
52
+/**@brief Worker state semaphore
53
+ * @ingroup IPC_flags */
54
+#define IPC_WREQS 4
55
+/**@brief Worker state semaphore
56
+ * @ingroup IPC_flags */
57
+#define IPC_SEMST 8
58
+/**@brief Worker state semaphore
59
+ * @ingroup IPC_flags */
60
+#define IPC_SHMST 16
61
+
62
+typedef unsigned short pyfcgi_ipc_flag_t;
63
+
64
+#include "conf.h"
65
+
66
+/**@brief Set semaphore names using master process PID as uniq key
67
+ * @param pid_t master process PID
68
+ */
69
+void pyfcgi_name_sems(pid_t master_pid);
70
+
71
+/**@brief Do shm_open & sem_open given component indicated by flag
72
+ * @param pyfcgi_ipc_flah_t flag a binary or combination of component flags
73
+ * @return 0 if no error else -1
74
+ * @note Stores the flag in configuration context 
75
+ * @see IPC_flags
76
+ */
77
+int pyfcgi_IPC_init(pyfcgi_ipc_flag_t flag);
78
+/**@brief Same than @ref pyfchi_IPC_init but with O_CREAT flag set */
79
+int pyfcgi_IPC_create(pyfcgi_ipc_flag_t flag);
80
+
81
+/**@brief Close previously opened IPC component (from conf context stored flag)
82
+ * @return 0 if no error else -1
83
+ */
84
+int pyfcgi_IPC_close();
85
+/**@brief IPC ressources cleanup */
86
+int pyfcgi_IPC_destroy(pyfcgi_ipc_flag_t flag);
87
+
88
+#endif

+ 1
- 1
include/pyutils.h View File

@@ -40,7 +40,7 @@ extern PyObject* libpyfcgi_self;
40 40
 void pyinit();
41 41
 
42 42
 /**@brief Add . to the embed pythonpath
43
- * @deprecated Py_SetPath breaks Py_GetPrefix()...
43
+ * @deprecated Py_SetPath breaks Py_GetPrefix()... now 
44 44
  */
45 45
 void update_python_path();
46 46
 

+ 8
- 5
include/responder.h View File

@@ -83,12 +83,15 @@ int responder_loop();
83 83
  */
84 84
 pid_t spawn(int);
85 85
 
86
-/**@brief Generate a new semaphore from given key
87
- * @ingroup work_master_proc
88
- * @note set pyfcgi_semid
89
- * @return int semid
86
+
87
+/**@deprecated Not used */
88
+int pyfcgi_pool_state();
89
+/**@brief Check if the pool is idle : if not able to timedwait the pool is busy
90
+ * @param const struct timespec timeout
91
+ * @return 1 if busy else 0
92
+ * @note exit on error
90 93
  */
91
-int new_semaphore();
94
+int pyfcgi_pool_idle(const struct timespec *timeout);
92 95
 
93 96
 /**@brief Exit after closing all stuff like semaphores
94 97
  * @ingroup work_master_proc

+ 2
- 2
src/Makefile.am View File

@@ -6,13 +6,13 @@ pyfcgi_LDADD = $(PYTHON_LDFLAGS)
6 6
 
7 7
 # libpyfcgi python module
8 8
 lib_LTLIBRARIES = libpyfcgi.la
9
-libpyfcgi_la_SOURCES = python_pyfcgi.c python_ioin.c
9
+libpyfcgi_la_SOURCES = python_pyfcgi.c python_ioin.c ipc.c
10 10
 libpyfcgi_la_CFLAGS = $(PYTHON_SO_CFLAGS)
11 11
 libpyfcgi_la_LDFLAGS = $(PYTHON_SO_LDFLAGS)
12 12
 
13 13
 # static librarie for check
14 14
 noinst_LIBRARIES = libpyfcgi.a
15
-libpyfcgi_a_SOURCES = logger.c pyworker.c responder.c conf.c pyutils.c python_pyfcgi.c python_ioin.c
15
+libpyfcgi_a_SOURCES = logger.c pyworker.c responder.c conf.c pyutils.c python_pyfcgi.c python_ioin.c ipc.c
16 16
 libpyfcgi_a_CFLAGS = $(PYTHON_CFLAGS)
17 17
 
18 18
 

+ 162
- 0
src/ipc.c View File

@@ -0,0 +1,162 @@
1
+#include "ipc.h"
2
+
3
+static const char *semnames[] = PYFCGI_SEMNAMES;
4
+static const pyfcgi_ipc_flag_t semflg[PYFCGI_NSEM] = {
5
+	IPC_WSTATE, IPC_WREQS, IPC_SEMST};
6
+
7
+void pyfcgi_name_sems(pid_t master_pid)
8
+{
9
+	short i;
10
+	for(i=0; i<PYFCGI_NSEM; i++)
11
+	{
12
+		if(snprintf(PyFCGI_conf.sems[i].name, NAME_MAX - 4,
13
+			PYFCGI_IPCNAME_FMT, master_pid, semnames[i]) < 0)
14
+		{
15
+			perror("Error allocating semaphore names");
16
+			exit(PYFCGI_FATAL);
17
+		}
18
+	}
19
+}
20
+
21
+int pyfcgi_IPC_create(pyfcgi_ipc_flag_t flag)
22
+{
23
+	short i;
24
+	int res, err;
25
+	
26
+	res = 0;
27
+	for(i=0; i<PYFCGI_NSEM; i++)
28
+	{
29
+		if(flag & semflg[i])
30
+		{
31
+			flag ^= semflg[i];
32
+			PyFCGI_SEM(i).sem = sem_open(PyFCGI_SEM(i).name, O_CREAT | O_EXCL,
33
+				0770, 0);
34
+			if(PyFCGI_SEM(i).sem == SEM_FAILED)
35
+			{
36
+				err = errno;
37
+				pyfcgi_log(LOG_ALERT,
38
+					"Unable to open semaphore %s(named '%s') : %s",
39
+					semnames[i], PyFCGI_SEM(i).name,
40
+					strerror(err));
41
+				PyFCGI_SEM(i).sem = NULL;
42
+				res = -1;
43
+			}
44
+			else
45
+			{
46
+				PyFCGI_conf.context.ipc_flag |= semflg[i];
47
+			}
48
+		}
49
+	}
50
+	if(flag & IPC_SHMST)
51
+	{
52
+		flag ^= IPC_SHMST;
53
+dprintf(2, "SHM not yet implemented...\n");
54
+res = -1;
55
+		//PyFCGI_conf.context.ipc_flag |= IPC_SHMST;
56
+	}
57
+	return res;
58
+}
59
+
60
+int pyfcgi_IPC_init(pyfcgi_ipc_flag_t flag)
61
+{
62
+	short i;
63
+	int res, err;
64
+	
65
+	res = 0;
66
+	for(i=0; i<PYFCGI_NSEM; i++)
67
+	{
68
+		if(flag & semflg[i])
69
+		{
70
+			flag ^= semflg[i];
71
+			PyFCGI_SEM(i).sem = sem_open(PyFCGI_SEM(i).name, 0);
72
+			if(PyFCGI_SEM(i).sem == SEM_FAILED)
73
+			{
74
+				err = errno;
75
+				pyfcgi_log(LOG_ALERT,
76
+					"Unable to open semaphore %s(named '%s') : %s",
77
+					semnames[i], PyFCGI_SEM(i).name,
78
+					strerror(err));
79
+				PyFCGI_SEM(i).sem = NULL;
80
+				res = -1;
81
+			}
82
+			else
83
+			{
84
+				PyFCGI_conf.context.ipc_flag |= semflg[i];
85
+			}
86
+		}
87
+	}
88
+	if(flag & IPC_SHMST)
89
+	{
90
+		flag ^= IPC_SHMST;
91
+dprintf(2, "SHM not yet implemented...\n");
92
+res = -1;
93
+		//PyFCGI_conf.context.ipc_flag |= IPC_SHMST;
94
+	}
95
+	return res;
96
+}
97
+
98
+int pyfcgi_IPC_close()
99
+{
100
+	short i;
101
+	int res, err;
102
+	pyfcgi_ipc_flag_t flag;
103
+
104
+	flag = PyFCGI_conf.context.ipc_flag;
105
+	res = 0;
106
+	for(i=0; i<PYFCGI_NSEM; i++)
107
+	{
108
+		if(flag & semflg[i])
109
+		{
110
+			continue;
111
+			PyFCGI_conf.context.ipc_flag ^= semflg[i];
112
+			if(sem_close(PyFCGI_SEM(i).sem) < 0)
113
+			{
114
+				err = errno;
115
+				pyfcgi_log(LOG_ALERT,
116
+					"Unable to close semaphore %s('%s') : %s",
117
+					semnames[i], PyFCGI_SEM(i).name,
118
+					strerror(err));
119
+				PyFCGI_SEM(i).sem = NULL;
120
+			}
121
+		}
122
+	}
123
+	if(flag & IPC_SHMST)
124
+	{
125
+dprintf(2, "SHM not yet implemented...\n");
126
+res = -1;
127
+		//PyFCGI_conf.context.ipc_flag ^= IPC_SHMST;
128
+	}
129
+
130
+	return res;
131
+}
132
+
133
+int pyfcgi_IPC_destroy(pyfcgi_ipc_flag_t flag)
134
+{
135
+	short i;
136
+	int err, res;
137
+	
138
+	res = 0;
139
+	for(i=0; i<PYFCGI_NSEM; i++)
140
+	{
141
+		if(flag & semflg[i])
142
+		{
143
+			if(sem_unlink(PyFCGI_SEM(i).name) < 0)
144
+			{
145
+				err = errno;
146
+				pyfcgi_log(LOG_ALERT,
147
+					"Unable to destroy %s semaphore (%s) : %s",
148
+					semnames[i], PyFCGI_SEM(i).name,
149
+					strerror(err));
150
+				res = -1;
151
+			}
152
+		}
153
+	}
154
+	if(flag & IPC_SHMST)
155
+	{
156
+dprintf(2, "SHM not yet implemented...\n");
157
+res = -1;
158
+		//PyFCGI_conf.context.ipc_flag ^= IPC_SHMST;
159
+	}
160
+	return res;
161
+}
162
+

+ 3
- 0
src/main.c View File

@@ -43,6 +43,7 @@
43 43
 #include "conf.h"
44 44
 #include "logger.h"
45 45
 #include "responder.h"
46
+#include "ipc.h"
46 47
 
47 48
 #define IDENT_FMT "pyfcgi[%d]"
48 49
 #define MAX_REQS 1024
@@ -119,6 +120,8 @@ int main(int argc, char **argv)
119 120
 
120 121
 	pool_handler_pid = 0;
121 122
 	default_conf();
123
+	pyfcgi_name_sems(getpid()); //name semaphore using master proc PID
124
+
122 125
 	pyfcgi_logger_init();
123 126
 	pyfcgi_logger_set_ident("MainProc");
124 127
 	if(parse_args(argc, argv))

+ 12
- 18
src/pyworker.c View File

@@ -595,18 +595,11 @@ int ctl_get_rep_sz(int ctl_pipe, size_t* rep_sz)
595 595
 static void worker_set_idle()
596 596
 {
597 597
 	int err;
598
-	struct sembuf sop;
599
-
600 598
 	if(_worker_idle) { return; }
601
-
602
-	sop.sem_num = 0;
603
-	sop.sem_flg = 0;
604
-	sop.sem_op = 1;
605
-
606
-	if(semop(PyFCGI_conf.context.semid, &sop, 1) < 0)
599
+	if(sem_post(PyFCGI_SEM(SEM_WSTATE).sem) < 0)
607 600
 	{
608 601
 		err = errno;
609
-		pyfcgi_log(LOG_ERR, "error incrementing the semaphore : %s",
602
+		pyfcgi_log(LOG_ERR, "error incrementing the WSTATE semaphore : %s",
610 603
 			strerror(err));
611 604
 		return;
612 605
 	}
@@ -616,18 +609,17 @@ static void worker_set_idle()
616 609
 static void worker_set_busy()
617 610
 {
618 611
 	int err;
619
-	struct sembuf sop;
620
-
621 612
 	if(!_worker_idle) { return; }
622
-	
623
-	sop.sem_num = 0;
624
-	sop.sem_flg = 0;
625
-	sop.sem_op = -1;
626
-
627
-	if(semop(PyFCGI_conf.context.semid, &sop, 1) < 0)
613
+	if(sem_trywait(PyFCGI_SEM(SEM_WSTATE).sem) < 0)
628 614
 	{
629 615
 		err = errno;
630
-		pyfcgi_log(LOG_ERR, "error incrementing the semaphore : %s",
616
+		if(err == EAGAIN)
617
+		{//panic
618
+			pyfcgi_log(LOG_ALERT, "Unable to set busy ! WSTATE sem is allready 0 !!!");
619
+			_worker_idle = 0;
620
+			return;
621
+		}
622
+		pyfcgi_log(LOG_ERR, "error decrementing the WSTATE semaphore : %s",
631 623
 			strerror(err));
632 624
 		return;
633 625
 	}
@@ -638,6 +630,7 @@ void worker_sighandler(int signum)
638 630
 {
639 631
 	pyfcgi_log(LOG_INFO, "%s signal received, exiting...", strsignal(signum));
640 632
 	worker_set_busy();
633
+	pyfcgi_IPC_close(IPC_WSTATE | IPC_WREQS);
641 634
 	exit(0);
642 635
 }
643 636
 
@@ -650,5 +643,6 @@ void worker_sigalrmhandler(int signum)
650 643
 		PyErr_SetInterrupt();
651 644
 	}
652 645
 	worker_set_busy();
646
+	pyfcgi_IPC_close(IPC_WSTATE | IPC_WREQS);
653 647
 	return;
654 648
 }

+ 82
- 43
src/responder.c View File

@@ -20,19 +20,38 @@
20 20
 
21 21
 void init_context()
22 22
 {
23
-	PyFCGI_conf.context.semid = 0;
24 23
 	PyFCGI_conf.context.pid = getpid();
25 24
 	PyFCGI_conf.context.ppid = getppid();
25
+
26
+	if(pyfcgi_IPC_create(IPC_WSTATE | IPC_WREQS | IPC_SEMST) < 0)
27
+	{
28
+		pyfcgi_log(LOG_ALERT, "Pool handler process is unable to create WSTATE SEM");
29
+		sleep(1);
30
+		clean_exit(PYFCGI_FATAL);
31
+	}
32
+	/*
33
+	if(pyfcgi_IPC_create(IPC_WSTATE) < 0)
34
+	{
35
+		pyfcgi_log(LOG_ALERT, "Pool handler process is unable to create WSTATE SEM");
36
+		sleep(1);
37
+		clean_exit(PYFCGI_FATAL);
38
+	}
39
+	if(pyfcgi_IPC_init(IPC_WREQS | IPC_SEMST) < 0)
40
+	{
41
+		pyfcgi_log(LOG_ALERT, "Pool handler process is unable to init IPC components");
42
+		sleep(1);
43
+		clean_exit(PYFCGI_FATAL);
44
+	}
45
+	*/
26 46
 }
27 47
 
28 48
 int responder_loop()
29 49
 {
30 50
 	unsigned int n_wrk, wanted_n, n;
31 51
 	pid_t *wrk_pids;
32
-	int semid, err;
52
+	int err;
33 53
 	int status;
34 54
 	pid_t ret;
35
-	struct sembuf sop;
36 55
 	/**@brief poll timeout */
37 56
 	struct timespec timeout;
38 57
 	/**@brief watchdog timeout */
@@ -54,9 +73,6 @@ int responder_loop()
54 73
 		exit(PYFCGI_FATAL);
55 74
 	}
56 75
 
57
-	sop.sem_num = 0;
58
-	sop.sem_op = 0;
59
-	sop.sem_flg = 0;
60 76
 	timeout.tv_sec = 0;
61 77
 	timeout.tv_nsec = 100000000;
62 78
 	idle = busy = 0;
@@ -89,8 +105,6 @@ int responder_loop()
89 105
 	}
90 106
 	bzero(wrk_pids, sizeof(int) * PyFCGI_conf.max_wrk);
91 107
 
92
-	PyFCGI_conf.context.semid = semid = new_semaphore();
93
-	
94 108
 	wanted_n = PyFCGI_conf.min_wrk;
95 109
 	n_wrk = 0;
96 110
 	// prespawning minimum worker count
@@ -100,7 +114,7 @@ int responder_loop()
100 114
 		PyFCGI_conf.context.n_wrk = n_wrk;
101 115
 	}
102 116
 	//Wait at least for a process to be ready
103
-	while(!semtimedop(semid, &sop, 1, &timeout));
117
+	while(!pyfcgi_pool_idle(&timeout));
104 118
 
105 119
 	// main loop, taking care to restart terminated workers, 
106 120
 	// spawn new one if needed, etc.
@@ -168,16 +182,8 @@ int responder_loop()
168 182
 		}
169 183
 
170 184
 		// Check if the pool is idle or busy
171
-		ret = semtimedop(semid, &sop, 1, &timeout);
172
-		if(ret < 0)
185
+		if(pyfcgi_pool_idle(&timeout))
173 186
 		{
174
-			err = errno;
175
-			if(err != EAGAIN)
176
-			{
177
-				pyfcgi_log(LOG_ERR, "Unable to read semaphore : %s",
178
-				       strerror(err));
179
-				exit(PYFCGI_FATAL);
180
-			}
181 187
 			// workers idle
182 188
 			busy = 0;
183 189
 			if(!idle)
@@ -193,7 +199,7 @@ int responder_loop()
193 199
 				idle = 0;
194 200
 			}
195 201
 		}
196
-		else if(!ret)
202
+		else
197 203
 		{
198 204
 			idle = 0;
199 205
 			if(!busy)
@@ -287,6 +293,12 @@ pid_t spawn(int wrk_id)
287 293
 		PyFCGI_conf.context.pid = getpid();
288 294
 		snprintf(ident, 128, "Worker%2d", wrk_id);
289 295
 		pyfcgi_logger_set_ident(ident);
296
+		// Init IPC components
297
+		if(pyfcgi_IPC_init(IPC_WSTATE | IPC_WREQS) < 0)
298
+		{
299
+			pyfcgi_log(LOG_ALERT, "Unable to initialize semaphore when spawning process...");
300
+			exit(PYFCGI_FATAL);
301
+		}
290 302
 		// Set handler for SIGINT & SIGTERM
291 303
 		if(sigaction(SIGINT, &act, NULL))
292 304
 		{
@@ -315,6 +327,7 @@ pid_t spawn(int wrk_id)
315 327
 			exit(work(wrk_id));
316 328
 		}
317 329
 	}
330
+	pyfcgi_IPC_init(IPC_WSTATE | IPC_WREQS | IPC_SEMST);
318 331
 	// Sleep to avoid spawning like hell thinking all workers are
319 332
 	// busy. Let some time to this one to go up...
320 333
 	// TODO: find a better way to avoid spawning to max_wrk
@@ -324,42 +337,68 @@ pid_t spawn(int wrk_id)
324 337
 	return res;
325 338
 }
326 339
 
327
-int new_semaphore(key_t semkey)
340
+int pyfcgi_pool_state()
328 341
 {
329
-	int semid, err;
330
-
331
-	semid = semget(IPC_PRIVATE, 2, 0770);
332
-
333
-	if(semid == -1)
342
+	int err, res;
343
+	if(sem_getvalue(PyFCGI_SEM(SEM_WSTATE).sem, &res) < 0)
334 344
 	{
335 345
 		err = errno;
336
-		pyfcgi_log(	LOG_ALERT,
337
-			"Unable to create semaphore : %s",
346
+		pyfcgi_log(LOG_ALERT, "Unable to read WSTATE semaphore value : %s",
338 347
 			strerror(err));
339
-		clean_exit(err);
348
+		clean_exit(PYFCGI_FATAL);
340 349
 	}
341
-	if(PyFCGI_conf.context.semid)
350
+	return res;
351
+}
352
+
353
+int pyfcgi_pool_idle(const struct timespec *timeout)
354
+{
355
+	int err;
356
+	struct timespec abs_timeout;
357
+
358
+	if(clock_gettime(CLOCK_REALTIME_COARSE, &abs_timeout) < 0)
359
+	{
360
+		//clock error
361
+		pyfcgi_log(LOG_WARNING, "Unable to fetch asbtime for WSTATE sem_timedwait : %s",
362
+			strerror(errno));
363
+	}
364
+	abs_timeout.tv_sec += timeout->tv_sec;
365
+	if(abs_timeout.tv_nsec + timeout->tv_nsec > 999999999)
366
+	{
367
+		abs_timeout.tv_nsec = abs_timeout.tv_nsec + timeout->tv_nsec - 999999999;
368
+		abs_timeout.tv_sec +=1;
369
+	}
370
+	else
342 371
 	{
343
-		pyfcgi_log(	LOG_WARNING,
344
-			"The semid context was not zero when calling new_semaphore, attempt to closeing it.");
345
-		semctl(PyFCGI_conf.context.semid, 0, IPC_RMID);
372
+		abs_timeout.tv_nsec = timeout->tv_nsec;
373
+	}
346 374
 
375
+	if(sem_timedwait(PyFCGI_SEM(SEM_WSTATE).sem, &abs_timeout) < 0)
376
+	{
377
+		err = errno;
378
+		switch(err)
379
+		{
380
+			case ETIMEDOUT:
381
+			case EAGAIN:
382
+				return 0; //busy
383
+			case EINVAL:
384
+				sleep(1);
385
+				return 1;
386
+			default:
387
+				pyfcgi_log(LOG_ALERT, "Unable to wait WSTATE sem : %s",
388
+					strerror(err));
389
+				clean_exit(PYFCGI_FATAL);
390
+		}
347 391
 	}
348
-	PyFCGI_conf.context.semid = semid;
349
-	return semid;
392
+	sem_post(PyFCGI_SEM(SEM_WSTATE).sem); //Hope no worker fails to set busy...
393
+	return 1; //idle
350 394
 }
351 395
 
352 396
 void clean_exit(int status)
353 397
 {
354
-	if(PyFCGI_conf.context.semid &&
355
-		semctl(PyFCGI_conf.context.semid, 0, IPC_RMID) == -1)
356
-	{
357
-		/*silentely fails (when exiting from sighandler)
358
-		pyfcgi_log(	LOG_CRIT,
359
-			"Unable to delete semaphore before exiting : %s",
360
-			strerror(errno));
361
-		*/
362
-	}
398
+	pyfcgi_IPC_close(IPC_WSTATE | IPC_WREQS | IPC_SEMST | IPC_SHMST);
399
+	//temporarly destroy everything....
400
+	pyfcgi_IPC_destroy(IPC_WSTATE | IPC_WREQS | IPC_SEMST | IPC_SHMST);
401
+	//pyfcgi_IPC_destroy(IPC_WSTATE);
363 402
 	exit(status);
364 403
 }
365 404
 

Loading…
Cancel
Save