feat:replace boost library with C++11 std library
This commit is contained in:
+515
@@ -0,0 +1,515 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_arch_threadproc.h"
|
||||
#include "apr_arch_file_io.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_portable.h"
|
||||
|
||||
#include <proc.h>
|
||||
|
||||
/* Heavy on no'ops, here's what we want to pass if there is APR_NO_FILE
|
||||
* requested for a specific child handle;
|
||||
*/
|
||||
static apr_file_t no_file = { NULL, -1, };
|
||||
|
||||
static apr_status_t apr_netware_proc_cleanup(void *theproc)
|
||||
{
|
||||
apr_proc_t *proc = theproc;
|
||||
int exit_int;
|
||||
int waitpid_options = WUNTRACED | WNOHANG;
|
||||
|
||||
if (proc->pid > 0) {
|
||||
waitpid(proc->pid, &exit_int, waitpid_options);
|
||||
}
|
||||
|
||||
/* NXVmDestroy(proc->pid); */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new,apr_pool_t *pool)
|
||||
{
|
||||
(*new) = (apr_procattr_t *)apr_pcalloc(pool, sizeof(apr_procattr_t));
|
||||
|
||||
if ((*new) == NULL) {
|
||||
return APR_ENOMEM;
|
||||
}
|
||||
(*new)->pool = pool;
|
||||
(*new)->cmdtype = APR_PROGRAM;
|
||||
/* Default to a current path since NetWare doesn't handle it very well */
|
||||
apr_filepath_get(&((*new)->currdir), APR_FILEPATH_NATIVE, pool);
|
||||
(*new)->detached = 1;
|
||||
return APR_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_io_set(apr_procattr_t *attr,
|
||||
apr_int32_t in,
|
||||
apr_int32_t out,
|
||||
apr_int32_t err)
|
||||
{
|
||||
apr_status_t rv;
|
||||
|
||||
if ((in != APR_NO_PIPE) && (in != APR_NO_FILE)) {
|
||||
/* APR_CHILD_BLOCK maps to APR_WRITE_BLOCK, while
|
||||
* APR_PARENT_BLOCK maps to APR_READ_BLOCK, so transpose
|
||||
* the CHILD/PARENT blocking flags for the stdin pipe.
|
||||
* stdout/stderr map to the correct mode by default.
|
||||
*/
|
||||
if (in == APR_CHILD_BLOCK)
|
||||
in = APR_READ_BLOCK;
|
||||
else if (in == APR_PARENT_BLOCK)
|
||||
in = APR_WRITE_BLOCK;
|
||||
|
||||
if ((rv = apr_file_pipe_create_ex(&attr->child_in, &attr->parent_in,
|
||||
in, attr->pool)) == APR_SUCCESS)
|
||||
rv = apr_file_inherit_unset(attr->parent_in);
|
||||
if (rv != APR_SUCCESS)
|
||||
return rv;
|
||||
}
|
||||
else if (in == APR_NO_FILE)
|
||||
attr->child_in = &no_file;
|
||||
|
||||
if ((out != APR_NO_PIPE) && (out != APR_NO_FILE)) {
|
||||
if ((rv = apr_file_pipe_create_ex(&attr->parent_out, &attr->child_out,
|
||||
out, attr->pool)) == APR_SUCCESS)
|
||||
rv = apr_file_inherit_unset(attr->parent_out);
|
||||
if (rv != APR_SUCCESS)
|
||||
return rv;
|
||||
}
|
||||
else if (out == APR_NO_FILE)
|
||||
attr->child_out = &no_file;
|
||||
|
||||
if ((err != APR_NO_PIPE) && (err != APR_NO_FILE)) {
|
||||
if ((rv = apr_file_pipe_create_ex(&attr->parent_err, &attr->child_err,
|
||||
err, attr->pool)) == APR_SUCCESS)
|
||||
rv = apr_file_inherit_unset(attr->parent_err);
|
||||
if (rv != APR_SUCCESS)
|
||||
return rv;
|
||||
}
|
||||
else if (err == APR_NO_FILE)
|
||||
attr->child_err = &no_file;
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_child_in_set(apr_procattr_t *attr, apr_file_t *child_in,
|
||||
apr_file_t *parent_in)
|
||||
{
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
|
||||
if (attr->child_in == NULL && attr->parent_in == NULL
|
||||
&& child_in == NULL && parent_in == NULL)
|
||||
if ((rv = apr_file_pipe_create(&attr->child_in, &attr->parent_in,
|
||||
attr->pool)) == APR_SUCCESS)
|
||||
rv = apr_file_inherit_unset(attr->parent_in);
|
||||
|
||||
if (child_in != NULL && rv == APR_SUCCESS) {
|
||||
if (attr->child_in && (attr->child_in->filedes != -1))
|
||||
rv = apr_file_dup2(attr->child_in, child_in, attr->pool);
|
||||
else {
|
||||
attr->child_in = NULL;
|
||||
if ((rv = apr_file_dup(&attr->child_in, child_in, attr->pool))
|
||||
== APR_SUCCESS)
|
||||
rv = apr_file_inherit_set(attr->child_in);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent_in != NULL && rv == APR_SUCCESS) {
|
||||
rv = apr_file_dup(&attr->parent_in, parent_in, attr->pool);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_child_out_set(apr_procattr_t *attr, apr_file_t *child_out,
|
||||
apr_file_t *parent_out)
|
||||
{
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
|
||||
if (attr->child_out == NULL && attr->parent_out == NULL
|
||||
&& child_out == NULL && parent_out == NULL)
|
||||
if ((rv = apr_file_pipe_create(&attr->parent_out, &attr->child_out,
|
||||
attr->pool)) == APR_SUCCESS)
|
||||
rv = apr_file_inherit_unset(attr->parent_out);
|
||||
|
||||
if (child_out != NULL && rv == APR_SUCCESS) {
|
||||
if (attr->child_out && (attr->child_out->filedes != -1))
|
||||
rv = apr_file_dup2(attr->child_out, child_out, attr->pool);
|
||||
else {
|
||||
attr->child_out = NULL;
|
||||
if ((rv = apr_file_dup(&attr->child_out, child_out, attr->pool))
|
||||
== APR_SUCCESS)
|
||||
rv = apr_file_inherit_set(attr->child_out);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent_out != NULL && rv == APR_SUCCESS) {
|
||||
rv = apr_file_dup(&attr->parent_out, parent_out, attr->pool);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_child_err_set(apr_procattr_t *attr, apr_file_t *child_err,
|
||||
apr_file_t *parent_err)
|
||||
{
|
||||
apr_status_t rv = APR_SUCCESS;
|
||||
|
||||
if (attr->child_err == NULL && attr->parent_err == NULL
|
||||
&& child_err == NULL && parent_err == NULL)
|
||||
if ((rv = apr_file_pipe_create(&attr->parent_err, &attr->child_err,
|
||||
attr->pool)) == APR_SUCCESS)
|
||||
rv = apr_file_inherit_unset(attr->parent_err);
|
||||
|
||||
if (child_err != NULL && rv == APR_SUCCESS) {
|
||||
if (attr->child_err && (attr->child_err->filedes != -1))
|
||||
rv = apr_file_dup2(attr->child_err, child_err, attr->pool);
|
||||
else {
|
||||
attr->child_err = NULL;
|
||||
if ((rv = apr_file_dup(&attr->child_err, child_err, attr->pool))
|
||||
== APR_SUCCESS)
|
||||
rv = apr_file_inherit_set(attr->child_err);
|
||||
}
|
||||
}
|
||||
|
||||
if (parent_err != NULL && rv == APR_SUCCESS) {
|
||||
rv = apr_file_dup(&attr->parent_err, parent_err, attr->pool);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr,
|
||||
const char *dir)
|
||||
{
|
||||
return apr_filepath_merge(&attr->currdir, NULL, dir,
|
||||
APR_FILEPATH_NATIVE, attr->pool);
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_cmdtype_set(apr_procattr_t *attr,
|
||||
apr_cmdtype_e cmd)
|
||||
{
|
||||
/* won't ever be called on this platform, so don't save the function pointer */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_detach_set(apr_procattr_t *attr, apr_int32_t detach)
|
||||
{
|
||||
attr->detached = detach;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
#if APR_HAS_FORK
|
||||
APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool)
|
||||
{
|
||||
int pid;
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
return errno;
|
||||
}
|
||||
else if (pid == 0) {
|
||||
proc->pid = pid;
|
||||
proc->in = NULL;
|
||||
proc->out = NULL;
|
||||
proc->err = NULL;
|
||||
return APR_INCHILD;
|
||||
}
|
||||
proc->pid = pid;
|
||||
proc->in = NULL;
|
||||
proc->out = NULL;
|
||||
proc->err = NULL;
|
||||
return APR_INPARENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static apr_status_t limit_proc(apr_procattr_t *attr)
|
||||
{
|
||||
#if APR_HAVE_STRUCT_RLIMIT && APR_HAVE_SETRLIMIT
|
||||
#ifdef RLIMIT_CPU
|
||||
if (attr->limit_cpu != NULL) {
|
||||
if ((setrlimit(RLIMIT_CPU, attr->limit_cpu)) != 0) {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef RLIMIT_NPROC
|
||||
if (attr->limit_nproc != NULL) {
|
||||
if ((setrlimit(RLIMIT_NPROC, attr->limit_nproc)) != 0) {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(RLIMIT_AS)
|
||||
if (attr->limit_mem != NULL) {
|
||||
if ((setrlimit(RLIMIT_AS, attr->limit_mem)) != 0) {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
#elif defined(RLIMIT_DATA)
|
||||
if (attr->limit_mem != NULL) {
|
||||
if ((setrlimit(RLIMIT_DATA, attr->limit_mem)) != 0) {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
#elif defined(RLIMIT_VMEM)
|
||||
if (attr->limit_mem != NULL) {
|
||||
if ((setrlimit(RLIMIT_VMEM, attr->limit_mem)) != 0) {
|
||||
return errno;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
/*
|
||||
* Maybe make a note in error_log that setrlimit isn't supported??
|
||||
*/
|
||||
|
||||
#endif
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_child_errfn_set(apr_procattr_t *attr,
|
||||
apr_child_errfn_t *errfn)
|
||||
{
|
||||
/* won't ever be called on this platform, so don't save the function pointer */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_error_check_set(apr_procattr_t *attr,
|
||||
apr_int32_t chk)
|
||||
{
|
||||
/* won't ever be used on this platform, so don't save the flag */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_addrspace_set(apr_procattr_t *attr,
|
||||
apr_int32_t addrspace)
|
||||
{
|
||||
attr->addrspace = addrspace;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *newproc,
|
||||
const char *progname,
|
||||
const char * const *args,
|
||||
const char * const *env,
|
||||
apr_procattr_t *attr,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
wiring_t wire;
|
||||
int addr_space;
|
||||
|
||||
wire.infd = attr->child_in
|
||||
? (attr->child_in->filedes != -1 ? attr->child_in->filedes
|
||||
: FD_UNUSED)
|
||||
: fileno(stdin);
|
||||
wire.outfd = attr->child_out
|
||||
? (attr->child_out->filedes != -1 ? attr->child_out->filedes
|
||||
: FD_UNUSED)
|
||||
: fileno(stdout);
|
||||
wire.errfd = attr->child_err
|
||||
? (attr->child_err->filedes != -1 ? attr->child_err->filedes
|
||||
: FD_UNUSED)
|
||||
: fileno(stderr);
|
||||
|
||||
newproc->in = attr->parent_in;
|
||||
newproc->out = attr->parent_out;
|
||||
newproc->err = attr->parent_err;
|
||||
|
||||
/* attr->detached and PROC_DETACHED do not mean the same thing. attr->detached means
|
||||
* start the NLM in a separate address space. PROC_DETACHED means don't wait for the
|
||||
* NLM to unload by calling wait() or waitpid(), just clean up */
|
||||
addr_space = PROC_LOAD_SILENT | (attr->addrspace ? 0 : PROC_CURRENT_SPACE);
|
||||
addr_space |= (attr->detached ? PROC_DETACHED : 0);
|
||||
|
||||
if (attr->currdir) {
|
||||
char *fullpath = NULL;
|
||||
apr_status_t rv;
|
||||
|
||||
if ((rv = apr_filepath_merge(&fullpath, attr->currdir, progname,
|
||||
APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) {
|
||||
return rv;
|
||||
}
|
||||
progname = fullpath;
|
||||
}
|
||||
|
||||
if ((newproc->pid = procve(progname, addr_space, (const char**)env, &wire,
|
||||
NULL, NULL, 0, NULL, (const char **)args)) == -1) {
|
||||
return errno;
|
||||
}
|
||||
|
||||
if (attr->child_in && (attr->child_in->filedes != -1)) {
|
||||
apr_pool_cleanup_kill(apr_file_pool_get(attr->child_in),
|
||||
attr->child_in, apr_unix_file_cleanup);
|
||||
apr_file_close(attr->child_in);
|
||||
}
|
||||
if (attr->child_out && (attr->child_out->filedes != -1)) {
|
||||
apr_pool_cleanup_kill(apr_file_pool_get(attr->child_out),
|
||||
attr->child_out, apr_unix_file_cleanup);
|
||||
apr_file_close(attr->child_out);
|
||||
}
|
||||
if (attr->child_err && (attr->child_err->filedes != -1)) {
|
||||
apr_pool_cleanup_kill(apr_file_pool_get(attr->child_err),
|
||||
attr->child_err, apr_unix_file_cleanup);
|
||||
apr_file_close(attr->child_err);
|
||||
}
|
||||
|
||||
apr_pool_cleanup_register(pool, (void *)newproc, apr_netware_proc_cleanup,
|
||||
apr_pool_cleanup_null);
|
||||
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc,
|
||||
int *exitcode,
|
||||
apr_exit_why_e *exitwhy,
|
||||
apr_wait_how_e waithow,
|
||||
apr_pool_t *p)
|
||||
{
|
||||
proc->pid = -1;
|
||||
return apr_proc_wait(proc, exitcode, exitwhy, waithow);
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_proc_wait(apr_proc_t *proc,
|
||||
int *exitcode, apr_exit_why_e *exitwhy,
|
||||
apr_wait_how_e waithow)
|
||||
{
|
||||
pid_t pstatus;
|
||||
int waitpid_options = WUNTRACED;
|
||||
int exit_int;
|
||||
int ignore;
|
||||
apr_exit_why_e ignorewhy;
|
||||
|
||||
if (exitcode == NULL) {
|
||||
exitcode = &ignore;
|
||||
}
|
||||
|
||||
if (exitwhy == NULL) {
|
||||
exitwhy = &ignorewhy;
|
||||
}
|
||||
|
||||
if (waithow != APR_WAIT) {
|
||||
waitpid_options |= WNOHANG;
|
||||
}
|
||||
|
||||
/* If the pid is 0 then the process was started detached. There
|
||||
is no need to wait since there is nothing to wait for on a
|
||||
detached process. Starting a process as non-detached and
|
||||
then calling wait or waitpid could cause the thread to hang.
|
||||
The reason for this is because NetWare does not have a way
|
||||
to kill or even signal a process to be killed. Starting
|
||||
all processes as detached avoids the possibility of a
|
||||
thread hanging. */
|
||||
if (proc->pid == 0) {
|
||||
*exitwhy = APR_PROC_EXIT;
|
||||
*exitcode = 0;
|
||||
return APR_CHILD_DONE;
|
||||
}
|
||||
|
||||
if ((pstatus = waitpid(proc->pid, &exit_int, waitpid_options)) > 0) {
|
||||
proc->pid = pstatus;
|
||||
|
||||
if (WIFEXITED(exit_int)) {
|
||||
*exitwhy = APR_PROC_EXIT;
|
||||
*exitcode = WEXITSTATUS(exit_int);
|
||||
}
|
||||
else if (WIFSIGNALED(exit_int)) {
|
||||
*exitwhy = APR_PROC_SIGNAL;
|
||||
*exitcode = WIFTERMSIG(exit_int);
|
||||
}
|
||||
else {
|
||||
/* unexpected condition */
|
||||
return APR_EGENERAL;
|
||||
}
|
||||
|
||||
return APR_CHILD_DONE;
|
||||
}
|
||||
else if (pstatus == 0) {
|
||||
return APR_CHILD_NOTDONE;
|
||||
}
|
||||
|
||||
return errno;
|
||||
}
|
||||
|
||||
#if APR_HAVE_STRUCT_RLIMIT
|
||||
APR_DECLARE(apr_status_t) apr_procattr_limit_set(apr_procattr_t *attr,
|
||||
apr_int32_t what,
|
||||
struct rlimit *limit)
|
||||
{
|
||||
switch(what) {
|
||||
case APR_LIMIT_CPU:
|
||||
#ifdef RLIMIT_CPU
|
||||
attr->limit_cpu = limit;
|
||||
break;
|
||||
#else
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
|
||||
case APR_LIMIT_MEM:
|
||||
#if defined(RLIMIT_DATA) || defined(RLIMIT_VMEM) || defined(RLIMIT_AS)
|
||||
attr->limit_mem = limit;
|
||||
break;
|
||||
#else
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
|
||||
case APR_LIMIT_NPROC:
|
||||
#ifdef RLIMIT_NPROC
|
||||
attr->limit_nproc = limit;
|
||||
break;
|
||||
#else
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
|
||||
case APR_LIMIT_NOFILE:
|
||||
#ifdef RLIMIT_NOFILE
|
||||
attr->limit_nofile = limit;
|
||||
break;
|
||||
#else
|
||||
return APR_ENOTIMPL;
|
||||
#endif
|
||||
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
#endif /* APR_HAVE_STRUCT_RLIMIT */
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_user_set(apr_procattr_t *attr,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
/* Always return SUCCESS because NetWare threads don't run as a user */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_group_set(apr_procattr_t *attr,
|
||||
const char *groupname)
|
||||
{
|
||||
/* Always return SUCCESS because NetWare threads don't run within a group */
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_procattr_perms_set_register(apr_procattr_t *attr,
|
||||
apr_perms_setfn_t *perms_set_fn,
|
||||
void *data,
|
||||
apr_fileperms_t perms)
|
||||
{
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_arch_threadproc.h"
|
||||
|
||||
apr_status_t apr_proc_detach(int daemonize)
|
||||
{
|
||||
#if 0
|
||||
int x;
|
||||
pid_t pgrp;
|
||||
|
||||
chdir("/");
|
||||
#if !defined(MPE) && !defined(OS2) && !defined(TPF) && !defined(BEOS)
|
||||
/* Don't detach for MPE because child processes can't survive the death of
|
||||
the parent. */
|
||||
if ((x = fork()) > 0)
|
||||
exit(0);
|
||||
else if (x == -1) {
|
||||
perror("fork");
|
||||
fprintf(stderr, "unable to fork new process\n");
|
||||
exit(1); /* we can't do anything here, so just exit. */
|
||||
}
|
||||
/* RAISE_SIGSTOP(DETACH);*/
|
||||
#endif
|
||||
#if APR_HAVE_SETSID
|
||||
if ((pgrp = setsid()) == -1) {
|
||||
return errno;
|
||||
}
|
||||
#elif defined(NEXT) || defined(NEWSOS)
|
||||
if (setpgrp(0, getpid()) == -1 || (pgrp = getpgrp(0)) == -1) {
|
||||
return errno;
|
||||
}
|
||||
#elif defined(OS2) || defined(TPF)
|
||||
/* OS/2 don't support process group IDs */
|
||||
pgrp = getpid();
|
||||
#elif defined(MPE)
|
||||
/* MPE uses negative pid for process group */
|
||||
pgrp = -getpid();
|
||||
#else
|
||||
if ((pgrp = setpgid(0, 0)) == -1) {
|
||||
return errno;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* close out the standard file descriptors */
|
||||
if (freopen("/dev/null", "r", stdin) == NULL) {
|
||||
return errno;
|
||||
/* continue anyhow -- note we can't close out descriptor 0 because we
|
||||
* have nothing to replace it with, and if we didn't have a descriptor
|
||||
* 0 the next file would be created with that value ... leading to
|
||||
* havoc.
|
||||
*/
|
||||
}
|
||||
if (freopen("/dev/null", "w", stdout) == NULL) {
|
||||
return errno;
|
||||
}
|
||||
/* We are going to reopen this again in a little while to the error
|
||||
* log file, but better to do it twice and suffer a small performance
|
||||
* hit for consistancy than not reopen it here.
|
||||
*/
|
||||
if (freopen("/dev/null", "w", stderr) == NULL) {
|
||||
return errno;
|
||||
}
|
||||
#endif
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if (!HAVE_WAITPID)
|
||||
/* From ikluft@amdahl.com
|
||||
* this is not ideal but it works for SVR3 variants
|
||||
* Modified by dwd@bell-labs.com to call wait3 instead of wait because
|
||||
* apache started to use the WNOHANG option.
|
||||
*/
|
||||
int waitpid(pid_t pid, int *statusp, int options)
|
||||
{
|
||||
int tmp_pid;
|
||||
if (kill(pid, 0) == -1) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
while (((tmp_pid = wait3(statusp, options, 0)) != pid) &&
|
||||
(tmp_pid != -1) && (tmp_pid != 0) && (pid != -1))
|
||||
;
|
||||
return tmp_pid;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_arch_threadproc.h"
|
||||
#include "apr_private.h"
|
||||
#include "apr_pools.h"
|
||||
#include "apr_signal.h"
|
||||
#include "apr_strings.h"
|
||||
|
||||
#include <assert.h>
|
||||
#if APR_HAS_THREADS && APR_HAVE_PTHREAD_H
|
||||
#include <pthread.h>
|
||||
#endif
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_proc_kill(apr_proc_t *proc, int signum)
|
||||
{
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
|
||||
|
||||
void apr_signal_init(apr_pool_t *pglobal)
|
||||
{
|
||||
}
|
||||
|
||||
const char *apr_signal_description_get(int signum)
|
||||
{
|
||||
switch (signum)
|
||||
{
|
||||
case SIGABRT:
|
||||
return "Abort";
|
||||
case SIGFPE:
|
||||
return "Arithmetic exception";
|
||||
case SIGILL:
|
||||
return "Illegal instruction";
|
||||
case SIGINT:
|
||||
return "Interrupt";
|
||||
case SIGSEGV:
|
||||
return "Segmentation fault";
|
||||
case SIGTERM:
|
||||
return "Terminated";
|
||||
case SIGPOLL:
|
||||
return "Pollable event occurred";
|
||||
default:
|
||||
return "unknown signal (not supported)";
|
||||
}
|
||||
}
|
||||
|
||||
static void *signal_thread_func(void *signal_handler)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND)
|
||||
APR_DECLARE(apr_status_t) apr_setup_signal_thread(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* (APR_HAVE_SIGWAIT || APR_HAVE_SIGSUSPEND) */
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_signal_block(int signum)
|
||||
{
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_signal_unblock(int signum)
|
||||
{
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr.h"
|
||||
#include "apr_portable.h"
|
||||
#include "apr_strings.h"
|
||||
#include "apr_arch_threadproc.h"
|
||||
|
||||
static int thread_count = 0;
|
||||
|
||||
apr_status_t apr_threadattr_create(apr_threadattr_t **new,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
(*new) = (apr_threadattr_t *)apr_palloc(pool,
|
||||
sizeof(apr_threadattr_t));
|
||||
|
||||
if ((*new) == NULL) {
|
||||
return APR_ENOMEM;
|
||||
}
|
||||
|
||||
(*new)->pool = pool;
|
||||
(*new)->stack_size = APR_DEFAULT_STACK_SIZE;
|
||||
(*new)->detach = 0;
|
||||
(*new)->thread_name = NULL;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
apr_status_t apr_threadattr_detach_set(apr_threadattr_t *attr,apr_int32_t on)
|
||||
{
|
||||
attr->detach = on;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
apr_status_t apr_threadattr_detach_get(apr_threadattr_t *attr)
|
||||
{
|
||||
if (attr->detach == 1)
|
||||
return APR_DETACH;
|
||||
return APR_NOTDETACH;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr,
|
||||
apr_size_t stacksize)
|
||||
{
|
||||
attr->stack_size = stacksize;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_threadattr_guardsize_set(apr_threadattr_t *attr,
|
||||
apr_size_t size)
|
||||
{
|
||||
return APR_ENOTIMPL;
|
||||
}
|
||||
|
||||
static void *dummy_worker(void *opaque)
|
||||
{
|
||||
apr_thread_t *thd = (apr_thread_t *)opaque;
|
||||
return thd->func(thd, thd->data);
|
||||
}
|
||||
|
||||
apr_status_t apr_thread_create(apr_thread_t **new,
|
||||
apr_threadattr_t *attr,
|
||||
apr_thread_start_t func,
|
||||
void *data,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
apr_status_t stat;
|
||||
unsigned long flags = NX_THR_BIND_CONTEXT;
|
||||
char threadName[NX_MAX_OBJECT_NAME_LEN+1];
|
||||
size_t stack_size = APR_DEFAULT_STACK_SIZE;
|
||||
|
||||
if (attr && attr->thread_name) {
|
||||
strncpy (threadName, attr->thread_name, NX_MAX_OBJECT_NAME_LEN);
|
||||
}
|
||||
else {
|
||||
sprintf(threadName, "APR_thread %04ld", ++thread_count);
|
||||
}
|
||||
|
||||
/* An original stack size of 0 will allow NXCreateThread() to
|
||||
* assign a default system stack size. An original stack
|
||||
* size of less than 0 will assign the APR default stack size.
|
||||
* anything else will be taken as is.
|
||||
*/
|
||||
if (attr && (attr->stack_size >= 0)) {
|
||||
stack_size = attr->stack_size;
|
||||
}
|
||||
|
||||
(*new) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
|
||||
|
||||
if ((*new) == NULL) {
|
||||
return APR_ENOMEM;
|
||||
}
|
||||
|
||||
(*new)->data = data;
|
||||
(*new)->func = func;
|
||||
(*new)->thread_name = (char*)apr_pstrdup(pool, threadName);
|
||||
|
||||
stat = apr_pool_create(&(*new)->pool, pool);
|
||||
if (stat != APR_SUCCESS) {
|
||||
return stat;
|
||||
}
|
||||
|
||||
if (attr && attr->detach) {
|
||||
flags |= NX_THR_DETACHED;
|
||||
}
|
||||
|
||||
(*new)->ctx = NXContextAlloc(
|
||||
/* void(*start_routine)(void *arg) */ (void (*)(void *)) dummy_worker,
|
||||
/* void *arg */ (*new),
|
||||
/* int priority */ NX_PRIO_MED,
|
||||
/* size_t stackSize */ stack_size,
|
||||
/* unsigned long flags */ NX_CTX_NORMAL,
|
||||
/* int *error */ &stat);
|
||||
|
||||
stat = NXContextSetName(
|
||||
/* NXContext_t ctx */ (*new)->ctx,
|
||||
/* const char *name */ threadName);
|
||||
|
||||
stat = NXThreadCreate(
|
||||
/* NXContext_t context */ (*new)->ctx,
|
||||
/* unsigned long flags */ flags,
|
||||
/* NXThreadId_t *thread_id */ &(*new)->td);
|
||||
|
||||
if (stat == 0)
|
||||
return APR_SUCCESS;
|
||||
|
||||
return(stat); /* if error */
|
||||
}
|
||||
|
||||
apr_os_thread_t apr_os_thread_current()
|
||||
{
|
||||
return NXThreadGetId();
|
||||
}
|
||||
|
||||
int apr_os_thread_equal(apr_os_thread_t tid1, apr_os_thread_t tid2)
|
||||
{
|
||||
return (tid1 == tid2);
|
||||
}
|
||||
|
||||
void apr_thread_yield()
|
||||
{
|
||||
NXThreadYield();
|
||||
}
|
||||
|
||||
apr_status_t apr_thread_exit(apr_thread_t *thd,
|
||||
apr_status_t retval)
|
||||
{
|
||||
thd->exitval = retval;
|
||||
apr_pool_destroy(thd->pool);
|
||||
NXThreadExit(NULL);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
apr_status_t apr_thread_join(apr_status_t *retval,
|
||||
apr_thread_t *thd)
|
||||
{
|
||||
apr_status_t stat;
|
||||
NXThreadId_t dthr;
|
||||
|
||||
if ((stat = NXThreadJoin(thd->td, &dthr, NULL)) == 0) {
|
||||
*retval = thd->exitval;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
|
||||
apr_status_t apr_thread_detach(apr_thread_t *thd)
|
||||
{
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
apr_status_t apr_thread_data_get(void **data, const char *key,
|
||||
apr_thread_t *thread)
|
||||
{
|
||||
if (thread != NULL) {
|
||||
return apr_pool_userdata_get(data, key, thread->pool);
|
||||
}
|
||||
else {
|
||||
data = NULL;
|
||||
return APR_ENOTHREAD;
|
||||
}
|
||||
}
|
||||
|
||||
apr_status_t apr_thread_data_set(void *data, const char *key,
|
||||
apr_status_t (*cleanup) (void *),
|
||||
apr_thread_t *thread)
|
||||
{
|
||||
if (thread != NULL) {
|
||||
return apr_pool_userdata_set(data, key, cleanup, thread->pool);
|
||||
}
|
||||
else {
|
||||
data = NULL;
|
||||
return APR_ENOTHREAD;
|
||||
}
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_os_thread_get(apr_os_thread_t **thethd,
|
||||
apr_thread_t *thd)
|
||||
{
|
||||
if (thd == NULL) {
|
||||
return APR_ENOTHREAD;
|
||||
}
|
||||
*thethd = &(thd->td);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_os_thread_put(apr_thread_t **thd,
|
||||
apr_os_thread_t *thethd,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
if (pool == NULL) {
|
||||
return APR_ENOPOOL;
|
||||
}
|
||||
if ((*thd) == NULL) {
|
||||
(*thd) = (apr_thread_t *)apr_palloc(pool, sizeof(apr_thread_t));
|
||||
(*thd)->pool = pool;
|
||||
}
|
||||
(*thd)->td = *thethd;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_thread_once_init(apr_thread_once_t **control,
|
||||
apr_pool_t *p)
|
||||
{
|
||||
(*control) = apr_pcalloc(p, sizeof(**control));
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control,
|
||||
void (*func)(void))
|
||||
{
|
||||
if (!atomic_xchg(&control->value, 1)) {
|
||||
func();
|
||||
}
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
APR_POOL_IMPLEMENT_ACCESSOR(thread)
|
||||
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "apr_portable.h"
|
||||
#include "apr_arch_threadproc.h"
|
||||
|
||||
apr_status_t apr_threadkey_private_create(apr_threadkey_t **key,
|
||||
void (*dest)(void *), apr_pool_t *pool)
|
||||
{
|
||||
apr_status_t stat;
|
||||
|
||||
(*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
|
||||
if ((*key) == NULL) {
|
||||
return APR_ENOMEM;
|
||||
}
|
||||
|
||||
(*key)->pool = pool;
|
||||
|
||||
if ((stat = NXKeyCreate(NULL, dest, &(*key)->key)) == 0) {
|
||||
return stat;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
apr_status_t apr_threadkey_private_get(void **new, apr_threadkey_t *key)
|
||||
{
|
||||
apr_status_t stat;
|
||||
|
||||
if ((stat = NXKeyGetValue(key->key, new)) == 0) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
|
||||
apr_status_t apr_threadkey_private_set(void *priv, apr_threadkey_t *key)
|
||||
{
|
||||
apr_status_t stat;
|
||||
if ((stat = NXKeySetValue(key->key, priv)) == 0) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return stat;
|
||||
}
|
||||
}
|
||||
|
||||
apr_status_t apr_threadkey_private_delete(apr_threadkey_t *key)
|
||||
{
|
||||
apr_status_t stat;
|
||||
if ((stat = NXKeyDelete(key->key)) == 0) {
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
return stat;
|
||||
}
|
||||
|
||||
apr_status_t apr_threadkey_data_get(void **data, const char *key, apr_threadkey_t *threadkey)
|
||||
{
|
||||
return apr_pool_userdata_get(data, key, threadkey->pool);
|
||||
}
|
||||
|
||||
apr_status_t apr_threadkey_data_set(void *data,
|
||||
const char *key, apr_status_t (*cleanup) (void *),
|
||||
apr_threadkey_t *threadkey)
|
||||
{
|
||||
return apr_pool_userdata_set(data, key, cleanup, threadkey->pool);
|
||||
}
|
||||
|
||||
apr_status_t apr_os_threadkey_get(apr_os_threadkey_t *thekey,
|
||||
apr_threadkey_t *key)
|
||||
{
|
||||
thekey = &(key->key);
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
apr_status_t apr_os_threadkey_put(apr_threadkey_t **key,
|
||||
apr_os_threadkey_t *thekey, apr_pool_t *pool)
|
||||
{
|
||||
if (pool == NULL) {
|
||||
return APR_ENOPOOL;
|
||||
}
|
||||
if ((*key) == NULL) {
|
||||
(*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t));
|
||||
(*key)->pool = pool;
|
||||
}
|
||||
(*key)->key = *thekey;
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user