Browse Source

Begin SHM support implementation for stats server process

Yann Weber 4 years ago
parent
commit
21acb49751
7 changed files with 144 additions and 28 deletions
  1. 19
    1
      include/conf.h
  2. 3
    1
      include/ipc.h
  3. 7
    0
      include/stats.h
  4. 99
    16
      src/ipc.c
  5. 3
    3
      src/main.c
  6. 12
    6
      src/monitor.c
  7. 1
    1
      src/responder.c

+ 19
- 1
include/conf.h View File

@@ -46,6 +46,7 @@ typedef struct pyfcgi_conf_s pyfcgi_conf_t;
46 46
 typedef struct pyfcgi_conf_logger_s pyfcgi_conf_logger_t;
47 47
 typedef struct pyfcgi_context_s pyfcgi_context_t;
48 48
 typedef struct pyfcgi_semdata_s pyfcgi_semdata_t;
49
+typedef struct pyfcgi_shmdata_s pyfcgi_shmdata_t;
49 50
 
50 51
 /**@brief Configuration globals, inherited from parent to childs
51 52
  * @ingroup conf_internal
@@ -141,13 +142,28 @@ Socket URL specification format : PROT://HOST[:PORT] with PROT on of \n\
141 142
 #define PYENTRY_DEFAULT_FUN "application"
142 143
 
143 144
 /**@brief Stores a semaphore name and pointer */
144
-struct pyfcgi_semdata_s {
145
+struct pyfcgi_semdata_s
146
+{
145 147
 	/**@brief Semaphore names. Set by master process */
146 148
 	char name[NAME_MAX - 4];
147 149
 	/**@brief Semaphore pointer. */
148 150
 	sem_t *sem;
149 151
 };
150 152
 
153
+/**@brief Stores an SHM name and pointer */
154
+struct pyfcgi_shmdata_s
155
+{
156
+	/**@brief SHM name. Set by master process */
157
+	char name[NAME_MAX];
158
+	/**@brief SHM file descriptor */
159
+	int fd;
160
+	/**@brief SHM size */
161
+	size_t len;
162
+
163
+	/**@brief SHM pointer */
164
+	void *ptr;
165
+};
166
+
151 167
 
152 168
 /**@brief Stores contextual informations about current process */
153 169
 struct pyfcgi_context_s {
@@ -252,6 +268,8 @@ struct pyfcgi_conf_s
252 268
 	 * - sems[2] is the stats/status SHM semaphore
253 269
 	 */
254 270
 	pyfcgi_semdata_t sems[PYFCGI_NSEM];
271
+	/**@brief Shared memory informations */
272
+	pyfcgi_shmdata_t shm;
255 273
 
256 274
 	/**@brief Stores a copy of the specified socket URL to listen to. */
257 275
 	char *mon_socket;

+ 3
- 1
include/ipc.h View File

@@ -28,6 +28,7 @@
28 28
 
29 29
 #include <fcntl.h>
30 30
 #include <semaphore.h>
31
+#include <sys/mman.h>
31 32
 #include <sys/stat.h>
32 33
 
33 34
 /**@brief Format for sem and shm */
@@ -64,11 +65,12 @@
64 65
 typedef unsigned short pyfcgi_ipc_flag_t;
65 66
 
66 67
 #include "conf.h"
68
+#include "stats.h" //to get SHM size
67 69
 
68 70
 /**@brief Set semaphore names using master process PID as uniq key
69 71
  * @param pid_t master process PID
70 72
  */
71
-void pyfcgi_name_sems(pid_t master_pid);
73
+void pyfcgi_name_IPC(pid_t master_pid);
72 74
 
73 75
 /**@brief Do shm_open & sem_open given component indicated by flag
74 76
  * @param pyfcgi_ipc_flah_t flag a binary or combination of component flags

+ 7
- 0
include/stats.h View File

@@ -31,6 +31,7 @@
31 31
 #define PYFCGI_STATS_SZ (900)
32 32
 
33 33
 typedef struct pyfcgi_stats_s pyfcgi_stats_t;
34
+typedef struct pyfcgi_stats_shm_s pyfcgi_stats_shm_t;
34 35
 
35 36
 #include "conf.h"
36 37
 #include "logger.h"
@@ -54,6 +55,12 @@ struct pyfcgi_stats_s
54 55
 	size_t buff_len;
55 56
 };
56 57
 
58
+struct pyfcgi_stats_shm_s
59
+{
60
+	int nworker;
61
+	int pool_load;
62
+};
63
+
57 64
 /**@brief Starts collecting statistics
58 65
  *
59 66
  * Set an handler for SIGALRM and set a repeating alarm each seconds

+ 99
- 16
src/ipc.c View File

@@ -4,7 +4,7 @@ static const char *semnames[] = PYFCGI_SEMNAMES;
4 4
 static const pyfcgi_ipc_flag_t semflg[PYFCGI_NSEM] = {
5 5
 	IPC_WSTATE, IPC_WREQS, IPC_SEMST};
6 6
 
7
-void pyfcgi_name_sems(pid_t master_pid)
7
+void pyfcgi_name_IPC(pid_t master_pid)
8 8
 {
9 9
 	short i;
10 10
 	for(i=0; i<PYFCGI_NSEM; i++)
@@ -16,6 +16,13 @@ void pyfcgi_name_sems(pid_t master_pid)
16 16
 			exit(PYFCGI_FATAL);
17 17
 		}
18 18
 	}
19
+	if(snprintf(PyFCGI_conf.shm.name, NAME_MAX, PYFCGI_IPCNAME_FMT,
20
+		master_pid, "SHMstats") < 0)
21
+	{
22
+		perror("Error setting shm name");
23
+		exit(PYFCGI_FATAL);
24
+	}
25
+	PyFCGI_conf.shm.len = sizeof(pyfcgi_stats_shm_t);
19 26
 }
20 27
 
21 28
 int pyfcgi_IPC_create(pyfcgi_ipc_flag_t flag)
@@ -29,13 +36,13 @@ int pyfcgi_IPC_create(pyfcgi_ipc_flag_t flag)
29 36
 		if(flag & semflg[i])
30 37
 		{
31 38
 			flag ^= semflg[i];
32
-			PyFCGI_SEM(i).sem = sem_open(PyFCGI_SEM(i).name, O_CREAT | O_EXCL,
33
-				0770, 0);
39
+			PyFCGI_SEM(i).sem = sem_open(PyFCGI_SEM(i).name,
40
+				O_CREAT | O_EXCL, 0770, 0);
34 41
 			if(PyFCGI_SEM(i).sem == SEM_FAILED)
35 42
 			{
36 43
 				err = errno;
37 44
 				pyfcgi_log(LOG_ALERT,
38
-					"Unable to open semaphore %s(named '%s') : %s",
45
+					"Unable to create semaphore %s(named '%s') : %s",
39 46
 					semnames[i], PyFCGI_SEM(i).name,
40 47
 					strerror(err));
41 48
 				PyFCGI_SEM(i).sem = NULL;
@@ -50,9 +57,39 @@ int pyfcgi_IPC_create(pyfcgi_ipc_flag_t flag)
50 57
 	if(flag & IPC_SHMST)
51 58
 	{
52 59
 		flag ^= IPC_SHMST;
53
-dprintf(2, "SHM not yet implemented...\n");
54
-res = -1;
55
-		//PyFCGI_conf.context.ipc_flag |= IPC_SHMST;
60
+		PyFCGI_conf.shm.fd = shm_open(PyFCGI_conf.shm.name,
61
+			O_RDWR | O_CREAT | O_EXCL, 0770);
62
+		if(PyFCGI_conf.shm.fd == -1)
63
+		{
64
+			err = errno;
65
+			pyfcgi_log(LOG_ALERT,
66
+				"Unable to create SHM '%s' : %s",
67
+				PyFCGI_conf.shm.name, strerror(errno));
68
+			PyFCGI_conf.shm.fd = 0;
69
+			return -1;
70
+		}
71
+		PyFCGI_conf.context.ipc_flag |= IPC_SHMST;
72
+		if(ftruncate(PyFCGI_conf.shm.fd,
73
+			sizeof(pyfcgi_stats_shm_t)) < 0)
74
+		{
75
+			pyfcgi_log(LOG_ALERT,
76
+				"Unable to truncate SHM to wanted size %ld : %s",
77
+				sizeof(pyfcgi_stats_shm_t),
78
+				strerror(errno));
79
+			pyfcgi_IPC_destroy(IPC_SHMST);
80
+			return -1;
81
+		}
82
+pyfcgi_log(LOG_INFO, "MMAP LENGHt : %ld", PyFCGI_conf.shm.len);
83
+		PyFCGI_conf.shm.ptr = mmap(NULL, PyFCGI_conf.shm.len,
84
+			PROT_READ | PROT_WRITE, MAP_SHARED, PyFCGI_conf.shm.fd,
85
+			0);
86
+		if(PyFCGI_conf.shm.ptr == (void*)-1)
87
+		{
88
+			pyfcgi_log(LOG_ALERT,
89
+				"Unable to mmap SHM : %s", strerror(errno));
90
+			pyfcgi_IPC_destroy(IPC_SHMST);
91
+			return -1;
92
+		}
56 93
 	}
57 94
 	return res;
58 95
 }
@@ -88,9 +125,27 @@ int pyfcgi_IPC_init(pyfcgi_ipc_flag_t flag)
88 125
 	if(flag & IPC_SHMST)
89 126
 	{
90 127
 		flag ^= IPC_SHMST;
91
-dprintf(2, "SHM not yet implemented...\n");
92
-res = -1;
93
-		//PyFCGI_conf.context.ipc_flag |= IPC_SHMST;
128
+		PyFCGI_conf.shm.fd = shm_open(PyFCGI_conf.shm.name, O_RDONLY, 0);
129
+		if(PyFCGI_conf.shm.fd == -1)
130
+		{
131
+			err = errno;
132
+			pyfcgi_log(LOG_ALERT,
133
+				"Unable to open SHM '%s' : %s",
134
+				PyFCGI_conf.shm.name, strerror(errno));
135
+			PyFCGI_conf.shm.fd = 0;
136
+			return -1;
137
+		}
138
+
139
+		PyFCGI_conf.context.ipc_flag |= IPC_SHMST;
140
+		PyFCGI_conf.shm.ptr = mmap(NULL, PyFCGI_conf.shm.len,
141
+			PROT_READ, MAP_SHARED, PyFCGI_conf.shm.fd, 0);
142
+		if(PyFCGI_conf.shm.ptr == (void*)-1)
143
+		{
144
+			pyfcgi_log(LOG_ALERT,
145
+				"Unable to mmap SHM : %s", strerror(errno));
146
+			pyfcgi_IPC_destroy(IPC_SHMST);
147
+			return -1;
148
+		}
94 149
 	}
95 150
 	return res;
96 151
 }
@@ -121,9 +176,20 @@ int pyfcgi_IPC_close()
121 176
 	}
122 177
 	if(flag & IPC_SHMST)
123 178
 	{
124
-dprintf(2, "SHM not yet implemented...\n");
125
-res = -1;
126
-		//PyFCGI_conf.context.ipc_flag ^= IPC_SHMST;
179
+		if(PyFCGI_conf.shm.ptr &&
180
+			munmap(PyFCGI_conf.shm.ptr, PyFCGI_conf.shm.len) < 0)
181
+		{
182
+			pyfcgi_log(LOG_WARNING, "Unable to unmap SHM : %s",
183
+				strerror(errno));
184
+		}
185
+		if(close(PyFCGI_conf.shm.fd) < 0)
186
+		{
187
+			pyfcgi_log(LOG_WARNING, "Unable to close SHM : %s",
188
+				strerror(errno));
189
+		}
190
+		PyFCGI_conf.shm.fd = 0;
191
+		PyFCGI_conf.shm.ptr = NULL;
192
+		PyFCGI_conf.context.ipc_flag ^= IPC_SHMST;
127 193
 	}
128 194
 
129 195
 	return res;
@@ -153,9 +219,26 @@ int pyfcgi_IPC_destroy(pyfcgi_ipc_flag_t flag)
153 219
 	}
154 220
 	if(flag & IPC_SHMST)
155 221
 	{
156
-dprintf(2, "SHM not yet implemented...\n");
157
-res = -1;
158
-		//PyFCGI_conf.context.ipc_flag ^= IPC_SHMST;
222
+
223
+		if(PyFCGI_conf.shm.ptr &&
224
+			munmap(PyFCGI_conf.shm.ptr, PyFCGI_conf.shm.len) < 0)
225
+		{
226
+			pyfcgi_log(LOG_WARNING, "Unable to unmap SHM : %s",
227
+				strerror(errno));
228
+		}
229
+		if(close(PyFCGI_conf.shm.fd) < 0)
230
+		{
231
+			pyfcgi_log(LOG_WARNING, "Unable to close SHM : %s",
232
+				strerror(errno));
233
+		}
234
+		if(shm_unlink(PyFCGI_conf.shm.name) < 0)
235
+		{
236
+			pyfcgi_log(LOG_WARNING, "Unabe to unlink SHM : %s",
237
+				strerror(errno));
238
+		}
239
+		PyFCGI_conf.shm.fd = 0;
240
+		PyFCGI_conf.shm.ptr = NULL;
241
+		PyFCGI_conf.context.ipc_flag ^= IPC_SHMST;
159 242
 	}
160 243
 	return res;
161 244
 }

+ 3
- 3
src/main.c View File

@@ -179,7 +179,7 @@ int main(int argc, char **argv)
179 179
 	pool_handler_pid = 0;
180 180
 	monitor_serv_pid = 0;
181 181
 	default_conf();
182
-	pyfcgi_name_sems(getpid()); //name semaphore using master proc PID
182
+	pyfcgi_name_IPC(getpid()); //name semaphore using master proc PID
183 183
 
184 184
 	pyfcgi_logger_init();
185 185
 	pyfcgi_logger_set_ident("MainProc");
@@ -271,8 +271,8 @@ int main(int argc, char **argv)
271 271
 		if(child_ret)
272 272
 		{
273 273
 
274
-			pyfcgi_log(LOG_ERR, "%s exits with error code '%d'",
275
-				child_name, WEXITSTATUS(child_ret));
274
+			pyfcgi_log(LOG_ERR, "%s exits with error code : %s",
275
+				child_name, status2str(WEXITSTATUS(child_ret)));
276 276
 			if(WIFSIGNALED(child_ret))
277 277
 			{
278 278
 				pyfcgi_log(LOG_ERR, "%s terminated by sig %s(%d)",

+ 12
- 6
src/monitor.c View File

@@ -98,15 +98,16 @@ int pyfcgi_monitor_IPC_init()
98 98
 	ret = 0;
99 99
 	if(!PyFCGI_SEM_OPEN(SEM_WREQS))
100 100
 	{
101
-		pyfcgi_IPC_init(IPC_WREQS);
102
-		ret = -1;
101
+		if(pyfcgi_IPC_init(IPC_WREQS)) { ret = -1; }
103 102
 	}
104 103
 	if(!PyFCGI_SEM_OPEN(SEM_STATS))
105 104
 	{
106
-		pyfcgi_IPC_init(IPC_SEMST);
107
-		ret = -1;
105
+		if(pyfcgi_IPC_init(IPC_SEMST)) { ret = -1; }
106
+	}
107
+	if(!PyFCGI_conf.shm.ptr)
108
+	{
109
+		if(pyfcgi_IPC_init(IPC_SHMST)) { ret = -1; }
108 110
 	}
109
-	//pyfcgi_IPC_init(IPC_SHMST);
110 111
 	return ret;
111 112
 }
112 113
 
@@ -168,7 +169,12 @@ void pyfcgi_monitor_loop()
168 169
 	pyfcgi_log(LOG_INFO, "Listening on %s", PyFCGI_conf.mon_socket);
169 170
 
170 171
 	//bind successfull, sending to appropriate response loop
171
-	pyfcgi_monitor_IPC_init(); //check returned value !
172
+	if(pyfcgi_monitor_IPC_init() < 0)
173
+	{
174
+		pyfcgi_log(LOG_ERR, "Unable to initialize IPC");
175
+		sleep(1);
176
+		exit(PYFCGI_ERR);
177
+	}
172 178
 	pyfcgi_stats_init();
173 179
 
174 180
 	if(pyfcgi_mon.sockargs[1] == SOCK_DGRAM)

+ 1
- 1
src/responder.c View File

@@ -63,7 +63,7 @@ void init_context()
63 63
 	PyFCGI_conf.context.pid = getpid();
64 64
 	PyFCGI_conf.context.ppid = getppid();
65 65
 
66
-	if(pyfcgi_IPC_create(IPC_WSTATE | IPC_WREQS | IPC_SEMST) < 0)
66
+	if(pyfcgi_IPC_create(IPC_WSTATE | IPC_WREQS | IPC_SEMST | IPC_SHMST) < 0)
67 67
 	{
68 68
 		pyfcgi_log(LOG_ALERT, "Pool handler process is unable to init IPC components");
69 69
 		sleep(1);

Loading…
Cancel
Save