~ubuntu-branches/ubuntu/feisty/apache2/feisty

« back to all changes in this revision

Viewing changes to srclib/apr/threadproc/netware/proc.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Barth
  • Date: 2006-12-09 21:05:45 UTC
  • mfrom: (0.6.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20061209210545-h70s0xaqc2v8vqr2
Tags: 2.2.3-3.2
* Non-maintainer upload.
* 043_ajp_connection_reuse: Patch from upstream Bugzilla, fixing a critical
  issue with regard to connection reuse in mod_proxy_ajp.
  Closes: #396265

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 
2
 * applicable.
 
3
 *
 
4
 * Licensed under the Apache License, Version 2.0 (the "License");
 
5
 * you may not use this file except in compliance with the License.
 
6
 * You may obtain a copy of the License at
 
7
 *
 
8
 *     http://www.apache.org/licenses/LICENSE-2.0
 
9
 *
 
10
 * Unless required by applicable law or agreed to in writing, software
 
11
 * distributed under the License is distributed on an "AS IS" BASIS,
 
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
13
 * See the License for the specific language governing permissions and
 
14
 * limitations under the License.
 
15
 */
 
16
 
 
17
#include "apr_arch_threadproc.h"
 
18
#include "apr_arch_file_io.h"
 
19
#include "apr_strings.h"
 
20
#include "apr_portable.h"
 
21
 
 
22
#include <proc.h>
 
23
 
 
24
apr_status_t apr_netware_proc_cleanup(void *theproc)
 
25
{
 
26
    apr_proc_t *proc = theproc;
 
27
    int exit_int;
 
28
    int waitpid_options = WUNTRACED | WNOHANG;
 
29
 
 
30
    if (proc->pid > 0) {
 
31
        waitpid(proc->pid, &exit_int, waitpid_options);
 
32
    }
 
33
 
 
34
/*      NXVmDestroy(proc->pid); */
 
35
    return APR_SUCCESS;
 
36
}
 
37
 
 
38
APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,apr_pool_t *pool)
 
39
{
 
40
    (*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t));
 
41
 
 
42
    if ((*new) == NULL) {
 
43
        return APR_ENOMEM;
 
44
    }
 
45
    (*new)->pool = pool;
 
46
    (*new)->cmdtype = APR_PROGRAM;
 
47
    /* Default to a current path since NetWare doesn't handle it very well */
 
48
    apr_filepath_get(&((*new)->currdir), APR_FILEPATH_NATIVE, pool);
 
49
    (*new)->detached = 1;
 
50
    return APR_SUCCESS;
 
51
 
 
52
}
 
53
 
 
54
APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr, apr_int32_t in, 
 
55
                                 apr_int32_t out, apr_int32_t err)
 
56
{
 
57
    apr_status_t status;
 
58
    if (in != 0) {
 
59
        if ((status = apr_file_pipe_create(&attr->child_in, &attr->parent_in, 
 
60
                                   attr->pool)) != APR_SUCCESS) {
 
61
            return status;
 
62
        }
 
63
        switch (in) {
 
64
        case APR_FULL_BLOCK:
 
65
            break;
 
66
        case APR_PARENT_BLOCK:
 
67
            apr_file_pipe_timeout_set(attr->child_in, 0);
 
68
            break;
 
69
        case APR_CHILD_BLOCK:
 
70
            apr_file_pipe_timeout_set(attr->parent_in, 0);
 
71
            break;
 
72
        default:
 
73
            apr_file_pipe_timeout_set(attr->child_in, 0);
 
74
            apr_file_pipe_timeout_set(attr->parent_in, 0);
 
75
        }
 
76
    } 
 
77
    if (out) {
 
78
        if ((status = apr_file_pipe_create(&attr->parent_out, &attr->child_out, 
 
79
                                   attr->pool)) != APR_SUCCESS) {
 
80
            return status;
 
81
        }
 
82
        switch (out) {
 
83
        case APR_FULL_BLOCK:
 
84
            break;
 
85
        case APR_PARENT_BLOCK:
 
86
            apr_file_pipe_timeout_set(attr->child_out, 0);
 
87
            break;
 
88
        case APR_CHILD_BLOCK:
 
89
            apr_file_pipe_timeout_set(attr->parent_out, 0);
 
90
            break;
 
91
        default:
 
92
            apr_file_pipe_timeout_set(attr->child_out, 0);
 
93
            apr_file_pipe_timeout_set(attr->parent_out, 0);
 
94
        }
 
95
    } 
 
96
    if (err) {
 
97
        if ((status = apr_file_pipe_create(&attr->parent_err, &attr->child_err, 
 
98
                                   attr->pool)) != APR_SUCCESS) {
 
99
            return status;
 
100
        }
 
101
        switch (err) {
 
102
        case APR_FULL_BLOCK:
 
103
            break;
 
104
        case APR_PARENT_BLOCK:
 
105
            apr_file_pipe_timeout_set(attr->child_err, 0);
 
106
            break;
 
107
        case APR_CHILD_BLOCK:
 
108
            apr_file_pipe_timeout_set(attr->parent_err, 0);
 
109
            break;
 
110
        default:
 
111
            apr_file_pipe_timeout_set(attr->child_err, 0);
 
112
            apr_file_pipe_timeout_set(attr->parent_err, 0);
 
113
        }
 
114
    } 
 
115
    return APR_SUCCESS;
 
116
}
 
117
 
 
118
 
 
119
APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
 
120
                                   apr_file_t *parent_in)
 
121
{
 
122
    if (attr->child_in == NULL && attr->parent_in == NULL)
 
123
        apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool);
 
124
 
 
125
    if (child_in != NULL)
 
126
        apr_file_dup2(attr->child_in, child_in, attr->pool);
 
127
 
 
128
    if (parent_in != NULL)
 
129
        apr_file_dup2(attr->parent_in, parent_in, attr->pool);
 
130
 
 
131
    return APR_SUCCESS;
 
132
}
 
133
 
 
134
 
 
135
APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
 
136
                                    apr_file_t *parent_out)
 
137
{
 
138
    if (attr->child_out == NULL && attr->parent_out == NULL)
 
139
        apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool);
 
140
 
 
141
    if (child_out != NULL)
 
142
        apr_file_dup2(attr->child_out, child_out, attr->pool);
 
143
 
 
144
    if (parent_out != NULL)
 
145
        apr_file_dup2(attr->parent_out, parent_out, attr->pool);
 
146
 
 
147
    return APR_SUCCESS;
 
148
}
 
149
 
 
150
 
 
151
APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
 
152
                                   apr_file_t *parent_err)
 
153
{
 
154
    if (attr->child_err == NULL && attr->parent_err == NULL)
 
155
        apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool);
 
156
 
 
157
    if (child_err != NULL)
 
158
        apr_file_dup2(attr->child_err, child_err, attr->pool);
 
159
 
 
160
    if (parent_err != NULL)
 
161
        apr_file_dup2(attr->parent_err, parent_err, attr->pool);
 
162
 
 
163
    return APR_SUCCESS;
 
164
}
 
165
 
 
166
 
 
167
APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, 
 
168
                               const char *dir) 
 
169
{
 
170
    return apr_filepath_merge(&attr->currdir, NULL, dir, 
 
171
                              APR_FILEPATH_NATIVE, attr->pool);
 
172
}
 
173
 
 
174
APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
 
175
                                     apr_cmdtype_e cmd) 
 
176
{
 
177
    /* won't ever be called on this platform, so don't save the function pointer */
 
178
    return APR_SUCCESS;
 
179
}
 
180
 
 
181
APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach) 
 
182
{
 
183
    attr->detached = detach;
 
184
    return APR_SUCCESS;
 
185
}
 
186
 
 
187
#if APR_HAS_FORK
 
188
APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
 
189
{
 
190
    int pid;
 
191
    
 
192
    if ((pid = fork()) < 0) {
 
193
        return errno;
 
194
    }
 
195
    else if (pid == 0) {
 
196
        proc->pid = pid;
 
197
        proc->in = NULL; 
 
198
        proc->out = NULL; 
 
199
        proc->err = NULL; 
 
200
        return APR_INCHILD;
 
201
    }
 
202
    proc->pid = pid;
 
203
    proc->in = NULL; 
 
204
    proc->out = NULL; 
 
205
    proc->err = NULL; 
 
206
    return APR_INPARENT;
 
207
}
 
208
#endif
 
209
 
 
210
static apr_status_t limit_proc(apr_procattr_t *attr)
 
211
{
 
212
#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT
 
213
#ifdef RLIMIT_CPU
 
214
    if (attr->limit_cpu != NULL) {
 
215
        if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) {
 
216
            return errno;
 
217
        }
 
218
    }
 
219
#endif
 
220
#ifdef RLIMIT_NPROC
 
221
    if (attr->limit_nproc != NULL) {
 
222
        if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) {
 
223
            return errno;
 
224
        }
 
225
    }
 
226
#endif
 
227
#if defined(RLIMIT_AS)
 
228
    if (attr->limit_mem != NULL) {
 
229
        if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) {
 
230
            return errno;
 
231
        }
 
232
    }
 
233
#elif defined(RLIMIT_DATA)
 
234
    if (attr->limit_mem != NULL) {
 
235
        if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) {
 
236
            return errno;
 
237
        }
 
238
    }
 
239
#elif defined(RLIMIT_VMEM)
 
240
    if (attr->limit_mem != NULL) {
 
241
        if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) {
 
242
            return errno;
 
243
        }
 
244
    }
 
245
#endif
 
246
#else
 
247
    /*
 
248
     * Maybe make a note in error_log that setrlimit isn't supported??
 
249
     */
 
250
 
 
251
#endif
 
252
    return APR_SUCCESS;
 
253
}
 
254
 
 
255
APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
 
256
                                                       apr_child_errfn_t *errfn)
 
257
{
 
258
    /* won't ever be called on this platform, so don't save the function pointer */
 
259
    return APR_SUCCESS;
 
260
}
 
261
 
 
262
APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
 
263
                                                       apr_int32_t chk)
 
264
{
 
265
    /* won't ever be used on this platform, so don't save the flag */
 
266
    return APR_SUCCESS;
 
267
}
 
268
 
 
269
APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
 
270
                                                       apr_int32_t addrspace)
 
271
{
 
272
    attr->addrspace = addrspace;
 
273
    return APR_SUCCESS;
 
274
}
 
275
 
 
276
APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *newproc,
 
277
                                                                        const char *progname, 
 
278
                                                                        const char * const *args, 
 
279
                                                                        const char * const *env,
 
280
                                        apr_procattr_t *attr, 
 
281
                                        apr_pool_t *pool)
 
282
{
 
283
        wiring_t                wire;
 
284
    int             addr_space;
 
285
 
 
286
    wire.infd  = attr->child_in ? attr->child_in->filedes : FD_UNUSED;
 
287
    wire.outfd = attr->child_out ? attr->child_out->filedes : FD_UNUSED;
 
288
    wire.errfd = attr->child_err ? attr->child_err->filedes : FD_UNUSED;
 
289
 
 
290
    newproc->in = attr->parent_in;
 
291
    newproc->out = attr->parent_out;
 
292
    newproc->err = attr->parent_err;
 
293
 
 
294
    /* attr->detached and PROC_DETACHED do not mean the same thing.  attr->detached means
 
295
     * start the NLM in a separate address space.  PROC_DETACHED means don't wait for the
 
296
     * NLM to unload by calling wait() or waitpid(), just clean up */
 
297
    addr_space = PROC_LOAD_SILENT | (attr->addrspace ? 0 : PROC_CURRENT_SPACE);
 
298
    addr_space |= (attr->detached ? PROC_DETACHED : 0);
 
299
 
 
300
    if (attr->currdir) {
 
301
        char *fullpath = NULL;
 
302
        apr_status_t rv;
 
303
 
 
304
        if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname, 
 
305
                                     APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) {
 
306
            return rv;
 
307
        }
 
308
        progname = fullpath;
 
309
    } 
 
310
 
 
311
    if ((newproc->pid = procve(progname, addr_space, (const char**)env, &wire, 
 
312
        NULL, NULL, 0, NULL, (const char **)args)) == -1) {
 
313
        return errno;
 
314
    }
 
315
 
 
316
    if (attr->child_in) {
 
317
        apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in), 
 
318
                              attr->child_in, apr_unix_file_cleanup);
 
319
        apr_file_close(attr->child_in);
 
320
    }
 
321
    if (attr->child_out) {
 
322
        apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out), 
 
323
                              attr->child_out, apr_unix_file_cleanup);
 
324
        apr_file_close(attr->child_out);
 
325
    }
 
326
    if (attr->child_err) {
 
327
        apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err), 
 
328
                              attr->child_err, apr_unix_file_cleanup);
 
329
        apr_file_close(attr->child_err);
 
330
    }
 
331
 
 
332
 
 
333
    apr_pool_cleanup_register(pool, (void *)newproc, apr_netware_proc_cleanup,
 
334
        apr_pool_cleanup_null);
 
335
 
 
336
    return APR_SUCCESS;
 
337
}
 
338
 
 
339
APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
 
340
                                                  int *exitcode,
 
341
                                                  apr_exit_why_e *exitwhy,
 
342
                                                  apr_wait_how_e waithow,
 
343
                                                  apr_pool_t *p)
 
344
{
 
345
    proc->pid = -1;
 
346
    return apr_proc_wait(proc, exitcode, exitwhy, waithow);
 
347
}
 
348
 
 
349
APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
 
350
                                        int *exitcode, apr_exit_why_e *exitwhy,
 
351
                                        apr_wait_how_e waithow)
 
352
{
 
353
    pid_t pstatus;
 
354
    int waitpid_options = WUNTRACED;
 
355
    int exit_int;
 
356
    int ignore;
 
357
    apr_exit_why_e ignorewhy;
 
358
 
 
359
    if (exitcode == NULL) {
 
360
        exitcode = &ignore;
 
361
    }
 
362
 
 
363
    if (exitwhy == NULL) {
 
364
        exitwhy = &ignorewhy;
 
365
    }
 
366
 
 
367
    if (waithow != APR_WAIT) {
 
368
        waitpid_options |= WNOHANG;
 
369
    }
 
370
 
 
371
    /* If the pid is 0 then the process was started detached. There 
 
372
       is no need to wait since there is nothing to wait for on a 
 
373
       detached process.  Starting a process as non-detached and
 
374
       then calling wait or waitpid could cause the thread to hang.
 
375
       The reason for this is because NetWare does not have a way 
 
376
       to kill or even signal a process to be killed.  Starting 
 
377
       all processes as detached avoids the possibility of a 
 
378
       thread hanging. */
 
379
    if (proc->pid == 0) {
 
380
        *exitwhy = APR_PROC_EXIT;
 
381
        *exitcode = 0;
 
382
        return APR_CHILD_DONE;
 
383
    }
 
384
 
 
385
    if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) {
 
386
        proc->pid = pstatus;
 
387
 
 
388
        if (WIFEXITED(exit_int)) {
 
389
            *exitwhy = APR_PROC_EXIT;
 
390
            *exitcode = WEXITSTATUS(exit_int);
 
391
        }
 
392
        else if (WIFSIGNALED(exit_int)) {
 
393
            *exitwhy = APR_PROC_SIGNAL;
 
394
            *exitcode = WIFTERMSIG(exit_int);
 
395
        }
 
396
        else {
 
397
            /* unexpected condition */
 
398
            return APR_EGENERAL;
 
399
        }
 
400
 
 
401
        return APR_CHILD_DONE;
 
402
    }
 
403
    else if (pstatus == 0) {
 
404
        return APR_CHILD_NOTDONE;
 
405
    }
 
406
 
 
407
    return errno;
 
408
}
 
409
 
 
410
APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr, apr_int32_t what, 
 
411
                          struct rlimit *limit)
 
412
{
 
413
    switch(what) {
 
414
        case APR_LIMIT_CPU:
 
415
#ifdef RLIMIT_CPU
 
416
            attr->limit_cpu = limit;
 
417
            break;
 
418
#else
 
419
            return APR_ENOTIMPL;
 
420
#endif
 
421
        case APR_LIMIT_MEM:
 
422
#if defined (RLIMIT_DATA) || defined (RLIMIT_VMEM) || defined(RLIMIT_AS)
 
423
            attr->limit_mem = limit;
 
424
            break;
 
425
#else
 
426
            return APR_ENOTIMPL;
 
427
#endif
 
428
        case APR_LIMIT_NPROC:
 
429
#ifdef RLIMIT_NPROC
 
430
            attr->limit_nproc = limit;
 
431
            break;
 
432
#else
 
433
            return APR_ENOTIMPL;
 
434
#endif
 
435
    }
 
436
    return APR_SUCCESS;
 
437
}  
 
438
 
 
439
APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr, 
 
440
                                                const char *username,
 
441
                                                const char *password)
 
442
{
 
443
    /* Always return SUCCESS because NetWare threads don't run as a user */
 
444
    return APR_SUCCESS;
 
445
}
 
446
 
 
447
APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
 
448
                                                 const char *groupname)
 
449
{
 
450
    /* Always return SUCCESS because NetWare threads don't run within a group */
 
451
    return APR_SUCCESS;
 
452
}