1 /* rivet_prefork_mpm.c: dynamically loaded MPM aware functions for prefork module */
2
3 /*
4 Licensed to the Apache Software Foundation (ASF) under one
5 or more contributor license agreements. See the NOTICE file
6 distributed with this work for additional information
7 regarding copyright ownership. The ASF licenses this file
8 to you under the Apache License, Version 2.0 (the
9 "License"); you may not use this file except in compliance
10 with the License. You may obtain a copy of the License at
11
12 http://www.apache.org/licenses/LICENSE-2.0
13
14 Unless required by applicable law or agreed to in writing,
15 software distributed under the License is distributed on an
16 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17 KIND, either express or implied. See the License for the
18 specific language governing permissions and limitations
19 under the License.
20 */
21
22 #include <apr_strings.h>
23
24 #include "mod_rivet.h"
25 #include "mod_rivet_common.h"
26 #include "mod_rivet_generator.h"
27 #include "mod_rivet_cache.h"
28 #include "httpd.h"
29 #include "rivetChannel.h"
30 #include "apache_config.h"
31 #include "rivet.h"
32 #include "rivetCore.h"
33 #include "worker_prefork_common.h"
34
35 extern DLLIMPORT mod_rivet_globals* module_globals;
36 extern DLLIMPORT apr_threadkey_t* rivet_thread_key;
37 extern module rivet_module;
38
39 rivet_thread_private* Rivet_VirtualHostsInterps (rivet_thread_private* private);
40
41 /* -- PreforkBridge_Finalize */
42
PreforkBridge_Finalize(void * data)43 apr_status_t PreforkBridge_Finalize (void* data)
44 {
45 rivet_thread_private* private;
46 server_rec* s = (server_rec*) data;
47
48 RIVET_PRIVATE_DATA_NOT_NULL(rivet_thread_key,private)
49 ap_log_error(APLOG_MARK, APLOG_DEBUG, APR_SUCCESS, s, "Running prefork bridge finalize method");
50
51 // No, we don't do any clean up anymore as we are just shutting this process down
52 // Rivet_ProcessorCleanup(private);
53
54 return OK;
55 }
56
57 /* -- PreforkBridge_ChildInit: bridge child process initialization
58 *
59 */
60
61
PreforkBridge_ChildInit(apr_pool_t * pool,server_rec * server)62 void PreforkBridge_ChildInit (apr_pool_t* pool, server_rec* server)
63 {
64 rivet_server_conf* rsc = RIVET_SERVER_CONF (module_globals->server->module_config);
65 rivet_thread_private* private;
66
67 ap_assert (apr_threadkey_private_create (&rivet_thread_key, NULL, pool) == APR_SUCCESS);
68
69 /*
70 * This is the only execution thread in this process so we create
71 * the Tcl thread private data here. In a fork capable OS
72 * private data should have been created by the httpd parent process
73 */
74
75 private = Rivet_ExecutionThreadInit();
76 private->ext = apr_pcalloc(private->pool,sizeof(mpm_bridge_specific));
77 private->ext->interps =
78 apr_pcalloc(private->pool,module_globals->vhosts_count*sizeof(rivet_thread_interp));
79
80
81 /* we now establish the full rivet core command set for the root interpreter */
82
83 Rivet_InitCore (module_globals->server_interp->interp,private);
84
85 /* The root interpreter is created without a rivet cache (that wouldn't make sense
86 * in that context. We create the cache now */
87
88 module_globals->server_interp->cache_size = rsc->default_cache_size;
89 if (module_globals->server_interp->cache_size < 0) {
90 module_globals->server_interp->cache_size = RivetCache_DefaultSize();
91 }
92 module_globals->server_interp->cache_free = module_globals->server_interp->cache_size;
93 ap_log_error(APLOG_MARK,APLOG_DEBUG,APR_SUCCESS,server,"root interpreter cache size: %d (free: %d)",
94 module_globals->server_interp->cache_size,
95 module_globals->server_interp->cache_free);
96
97 RivetCache_Create(module_globals->pool,module_globals->server_interp);
98
99 #ifdef RIVET_NAMESPACE_IMPORT
100 {
101 char* tcl_import_cmd = "namespace eval :: { namespace import -force ::rivet::* }\n";
102
103 Tcl_Eval (module_globals->server_interp->interp,tcl_import_cmd);
104 }
105 #endif
106
107 /*
108 * We proceed creating the vhost interpreters database
109 */
110
111 if (Rivet_VirtualHostsInterps(private) == NULL)
112 {
113 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server, MODNAME ": Tcl Interpreters creation fails");
114 exit(1);
115 }
116 }
117
118 /*
119 * -- PreforkBridge_Request
120 *
121 * The prefork implementation of this function is basically a wrapper of
122 * Rivet_SendContent. The real job is fetching the thread private data
123 *
124 * Arguments:
125 *
126 * request_rec* rec
127 *
128 * Returned value:
129 *
130 * HTTP status code (see the Apache HTTP web server documentation)
131 */
132
PreforkBridge_Request(request_rec * r,rivet_req_ctype ctype)133 int PreforkBridge_Request (request_rec* r,rivet_req_ctype ctype)
134 {
135 rivet_thread_private* private;
136
137 /* fetching the thread private data to be passed to Rivet_SendContent */
138
139 RIVET_PRIVATE_DATA_NOT_NULL (rivet_thread_key, private);
140
141 private->ctype = ctype;
142 private->req_cnt++;
143 private->r = r;
144
145 return Rivet_SendContent(private);
146 }
147
148 /*
149 * -- MPM_MasterInterp
150 *
151 *
152 *
153 */
154
MPM_MasterInterp(server_rec * server)155 rivet_thread_interp* MPM_MasterInterp(server_rec* server)
156 {
157 rivet_thread_private* private;
158 int tcl_status;
159
160 RIVET_PRIVATE_DATA_NOT_NULL (rivet_thread_key, private);
161
162 module_globals->server_interp->channel = private->channel;
163
164 /*
165 * We are returning the interpreter inherited from
166 * the parent process. The fork preserves the internal status
167 * of the process, math engine status included. This fact implies
168 * the random number generator has the same seed and every
169 * child process for which SeparateVirtualInterps would generate
170 * the same random number sequence. We therefore reseed the RNG
171 * calling a Tcl script fragment
172 */
173
174 tcl_status = Tcl_Eval(module_globals->server_interp->interp,"expr {srand([clock clicks] + [pid])}");
175 if (tcl_status != TCL_OK)
176 {
177 ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, server,
178 MODNAME ": Tcl interpreter random number generation reseeding failed");
179
180 }
181 return module_globals->server_interp;
182 }
183
184 /*
185 * -- PreforkBridge_ExitHandler
186 *
187 * Just calling Tcl_Exit
188 *
189 * Arguments:
190 * int code
191 *
192 * Side Effects:
193 *
194 * the thread running the Tcl script will exit
195 */
196
PreforkBridge_ExitHandler(rivet_thread_private * private)197 int PreforkBridge_ExitHandler(rivet_thread_private* private)
198 {
199 Tcl_Exit(private->exit_status);
200
201 /* actually we'll never get here but we return
202 * the Tcl return code anyway to silence the
203 * compilation warning
204 */
205 return TCL_OK;
206 }
207
PreforkBridge_Interp(rivet_thread_private * private,rivet_server_conf * conf,rivet_thread_interp * interp)208 rivet_thread_interp* PreforkBridge_Interp (rivet_thread_private* private,
209 rivet_server_conf* conf,
210 rivet_thread_interp* interp)
211 {
212 if (interp != NULL) { private->ext->interps[conf->idx] = interp; }
213
214 return private->ext->interps[conf->idx];
215 }
216
217 /*
218 * -- PreforkBridge_ServerInit
219 *
220 * Bridge server wide inizialization:
221 *
222 */
223
PreforkBridge_ServerInit(apr_pool_t * pPool,apr_pool_t * pLog,apr_pool_t * pTemp,server_rec * s)224 int PreforkBridge_ServerInit (apr_pool_t* pPool,apr_pool_t* pLog,apr_pool_t* pTemp,server_rec* s)
225 {
226 /* Whether single_thread_exit is 1 or 0 doesn't make any difference for
227 * the prefork bridge, we set the default value anyway in case it hadn't been
228 * set already in the configuration */
229
230 if (module_globals->single_thread_exit == SINGLE_THREAD_EXIT_UNDEF)
231 {
232 module_globals->single_thread_exit = 0;
233 }
234
235 /* The root interpreter is created without a rivet cache (that wouldn't make sense
236 * in that context. We create the cache now */
237
238 if (module_globals->server_interp->cache_size) {
239 RivetCache_Create(pPool,module_globals->server_interp);
240 }
241 return OK;
242 }
243
244 /* Table of bridge control functions */
245
246 DLLEXPORT
247 RIVET_MPM_BRIDGE {
248 PreforkBridge_ServerInit,
249 PreforkBridge_ChildInit,
250 PreforkBridge_Request,
251 PreforkBridge_Finalize,
252 PreforkBridge_ExitHandler,
253 PreforkBridge_Interp
254 };
255
256