configure: CFLAGS="-I/boot/home/develop/flock_server/src/headers -I/boot/home/config/include" CPPFLAGS="-I/boot/home/develop/flock_server/src/headers -I/boot/home/config/include" LDFLAGS="-L/boot/home/config/lib -lflock -liconv -no-undefined" ./configure --prefix=/boot/home/config --with-libtool diff -urN apr-1.0.1.orig/build/apr_hints.m4 apr-1.0.1/build/apr_hints.m4 --- apr-1.0.1.orig/build/apr_hints.m4 2004-11-17 02:07:02.000000000 +0100 +++ apr-1.0.1/build/apr_hints.m4 2004-12-17 15:19:10.000000000 +0100 @@ -351,7 +351,6 @@ *beos*) APR_ADDTO(CPPFLAGS, [-DBEOS]) PLATOSVERS=`uname -r` - APR_SETIFNULL(apr_process_lock_is_global, [yes]) case $PLATOSVERS in 5.0.4) APR_ADDTO(LDFLAGS, [-L/boot/beos/system/lib]) @@ -362,6 +361,9 @@ APR_ADDTO(LDFLAGS, [-L/boot/beos/system/lib]) APR_ADDTO(LIBS, [-lbind -lsocket]) ;; + *) + APR_ADDTO(LDFLAGS,-lnet) + ;; esac APR_ADDTO(CPPFLAGS, [-DSIGPROCMASK_SETS_THREAD_MASK -DAP_AUTH_DBM_USE_APR]) ;; diff -urN apr-1.0.1.orig/configure.in apr-1.0.1/configure.in --- apr-1.0.1.orig/configure.in 2004-11-17 02:07:02.000000000 +0100 +++ apr-1.0.1/configure.in 2004-12-17 15:19:10.000000000 +0100 @@ -221,7 +221,7 @@ dnl otherwise. case $host in - *os390) + *os390 | *beos) if test "$ac_test_CFLAGS" != set; then APR_REMOVEFROM(CFLAGS,-g) fi @@ -232,6 +232,10 @@ [APR_ADDTO(CFLAGS,-g) if test "$GCC" = "yes"; then APR_ADDTO(CFLAGS,-Wall) + if test "$host" = "i586-pc-beos"; then + APR_REMOVEFROM(CFLAGS, -O2) + APR_ADDTO(CFLAGS, -O0) + fi elif test "$AIX_XLC" = "yes"; then APR_ADDTO(CFLAGS,-qfullpath) fi @@ -384,10 +388,9 @@ APR_CHECK_DEFINE(BONE_VERSION, sys/socket.h) eolstr="\\n" osver=`uname -r` - proc_mutex_is_global=1 OBJECTS_PLATFORM='$(OBJECTS_beos)' case $osver in - 5.0.4) + 5.0.4 | 5.1) file_as_socket="1" ;; *) @@ -715,6 +718,7 @@ haveshmgetanon="0" havemmapzero="0" havemmapanon="0" +havebeosarea="0" APR_BEGIN_DECISION([anonymous shared memory allocation method]) APR_IFALLYES(header:sys/ipc.h header:sys/shm.h header:sys/file.h dnl func:shmget func:shmat func:shmdt func:shmctl, @@ -732,7 +736,7 @@ [haveos2shm="1" APR_DECIDE(USE_SHMEM_OS2_ANON, [OS/2 DosAllocSharedMem()])]) APR_IFALLYES(header:kernel/OS.h func:create_area, - [havebeosshm="1" + [havebeosarea="1" APR_DECIDE(USE_SHMEM_BEOS_ANON, [BeOS areas])]) case $host in @@ -779,7 +783,6 @@ havemmaptmp="0" havemmapshm="0" haveshmget="0" -havebeosarea="0" haveos2shm="0" APR_BEGIN_DECISION([namebased memory allocation method]) APR_IFALLYES(header:sys/mman.h func:mmap func:munmap, @@ -796,7 +799,7 @@ [haveshmget="1" APR_DECIDE(USE_SHMEM_SHMGET, [SysV IPC shmget()])]) APR_IFALLYES(header:kernel/OS.h func:create_area, - [havebeosshm="1" + [havebeosarea="1" APR_DECIDE(USE_SHMEM_BEOS, [BeOS areas])]) APR_IFALLYES(header:os2.h, [haveos2shm="1" @@ -1315,9 +1318,10 @@ size_t_fmt='#define APR_SIZE_T_FMT "ld"' ;; *beos*) - ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"' - size_t_fmt='#define APR_SIZE_T_FMT "ld"' - ;; + pid_t_fmt='#define APR_PID_T_FMT "ld"' + ssize_t_fmt='#define APR_SSIZE_T_FMT "ld"' + size_t_fmt='#define APR_SIZE_T_FMT "ld"' + ;; *apple-darwin*) ssize_t_fmt='#define APR_SSIZE_T_FMT "d"' size_t_fmt='#define APR_SIZE_T_FMT "lu"' @@ -1399,6 +1403,10 @@ # Original HP-UX: AC_CHECK_LIB(dld, shl_load, [dsotype=shl; APR_ADDTO(LIBS,-ldld)]) fi + if test "$dsotype" = "any"; then + # BeOS: + AC_CHECK_LIB(root, load_image, [dsotype=other]) + fi # Normal POSIX: if test "$dsotype" = "any"; then AC_CHECK_FUNC(dlopen, [dsotype=dlfcn]) @@ -1414,10 +1422,6 @@ [dsotype=any echo "Weird: dlopen() was found but dlsym() was not found!"])]) fi - if test "$dsotype" = "any"; then - # BeOS: - AC_CHECK_LIB(root, load_image, [dsotype=other]) - fi # Everything else: if test "$dsotype" = "any"; then case $host in @@ -1597,6 +1601,17 @@ fi fi +# BeOS has no built-in flock(), but there is a third-party flock_server package +# that adds basic (if not compliant) support. It defines flock() in flock.h. +case $host in + *beos) + unset ac_cv_define_LOCK_EX + APR_CHECK_DEFINE(LOCK_EX, flock.h) + APR_IFALLYES(func:flock define:LOCK_EX, [ + APR_ADDTO(CFLAGS, -Dclose=flock_close -Ddup2=flock_dup2)]) + ;; +esac + # See which lock mechanisms we can support on this system. APR_IFALLYES(header:semaphore.h func:sem_open func:sem_close dnl func:sem_unlink func:sem_post func:sem_wait, @@ -1610,7 +1625,16 @@ func:pthread_mutexattr_setpshared dnl file:/dev/zero, hasprocpthreadser="1", hasprocpthreadser="0") -APR_IFALLYES(header:OS.h func:create_sem, hasbeossem="1", hasbeossem="0") +APR_IFALLYES(header:OS.h func:create_sem, hasbeossemser="1", hasbeossemser="0") + +# BeOS defines F_SETLK, but that doesn't mean, that it really works. +case $host in + *beos*) + hasfcntlser="0" + ;; + *) + ;; +esac # See which lock mechanism we'll select by default on this system. # The last APR_DECIDE to execute sets the default. @@ -1642,6 +1666,7 @@ posixser="0" procpthreadser="0" fcntlser="0" +beossemser="0" case $ac_decision in USE_FLOCK_SERIALIZE ) flockser="1" @@ -1659,7 +1684,7 @@ procpthreadser="1" ;; USE_BEOSSEM ) - beossem="1" + beossemser="1" ;; esac @@ -1668,12 +1693,14 @@ AC_SUBST(hasposixser) AC_SUBST(hasfcntlser) AC_SUBST(hasprocpthreadser) +AC_SUBST(hasbeossemser) AC_SUBST(flockser) AC_SUBST(sysvser) AC_SUBST(posixser) AC_SUBST(fcntlser) AC_SUBST(procpthreadser) AC_SUBST(pthreadser) +AC_SUBST(beossemser) AC_MSG_CHECKING(if all interprocess locks affect threads) if test "x$apr_process_lock_is_global" = "xyes"; then @@ -1983,6 +2010,9 @@ if test -d $srcdir/test; then MAKEFILES="$MAKEFILES test/Makefile test/internal/Makefile" fi +if test -d $srcdir/threadproc/beos; then + MAKEFILES="$MAKEFILES threadproc/beos/Makefile" +fi # # BSD/OS (BSDi) needs to use a different include syntax in the Makefiles diff -urN apr-1.0.1.orig/dso/beos/dso.c apr-1.0.1/dso/beos/dso.c --- apr-1.0.1.orig/dso/beos/dso.c 2004-03-09 15:40:41.000000000 +0100 +++ apr-1.0.1/dso/beos/dso.c 2004-12-17 15:19:10.000000000 +0100 @@ -22,7 +22,7 @@ { apr_dso_handle_t *dso = thedso; - if (dso->handle > 0 && unload_add_on(dso->handle) < B_NO_ERROR) + if (dso->handle >= 0 && unload_add_on(dso->handle) < B_NO_ERROR) return APR_EINIT; dso->handle = -1; @@ -32,19 +32,16 @@ APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle, const char *path, apr_pool_t *pool) { - image_id newid = -1; + apr_dso_handle_t *handle = apr_pcalloc(pool, sizeof(apr_dso_handle_t)); + *res_handle = handle; - *res_handle = apr_pcalloc(pool, sizeof(*res_handle)); - - if((newid = load_add_on(path)) < B_NO_ERROR) { - (*res_handle)->errormsg = strerror(newid); + handle->handle = load_add_on(path); + if (handle->handle < B_NO_ERROR) return APR_EDSOOPEN; - } - - (*res_handle)->pool = pool; - (*res_handle)->handle = newid; - apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null); + handle->pool = pool; + + apr_pool_cleanup_register(pool, handle, dso_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; } @@ -62,10 +59,9 @@ if (symname == NULL) return APR_ESYMNOTFOUND; - err = get_image_symbol(handle->handle, symname, B_SYMBOL_TYPE_ANY, - ressym); + err = get_image_symbol(handle->handle, symname, B_SYMBOL_TYPE_ANY, ressym); - if(err != B_OK) + if (err != B_OK) return APR_ESYMNOTFOUND; return APR_SUCCESS; diff -urN apr-1.0.1.orig/file_io/unix/flock.c apr-1.0.1/file_io/unix/flock.c --- apr-1.0.1.orig/file_io/unix/flock.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/file_io/unix/flock.c 2004-12-17 15:19:10.000000000 +0100 @@ -22,11 +22,15 @@ #include #endif +#if defined(BEOS) && APR_HAS_FLOCK_SERIALIZE +#include +#endif + APR_DECLARE(apr_status_t) apr_file_lock(apr_file_t *thefile, int type) { int rc; -#if defined(HAVE_FCNTL_H) +#if APR_HAS_FCNTL_SERIALIZE { struct flock l = { 0 }; int fc; @@ -56,7 +60,7 @@ return errno; } } -#elif defined(HAVE_SYS_FILE_H) +#elif APR_HAS_FLOCK_SERIALIZE { int ltype; @@ -85,7 +89,7 @@ { int rc; -#if defined(HAVE_FCNTL_H) +#if APR_HAS_FCNTL_SERIALIZE { struct flock l = { 0 }; @@ -102,7 +106,7 @@ if (rc == -1) return errno; } -#elif defined(HAVE_SYS_FILE_H) +#elif APR_HAS_FLOCK_SERIALIZE { /* keep trying if flock() gets interrupted (by a signal) */ while ((rc = flock(thefile->filedes, LOCK_UN)) < 0 && errno == EINTR) diff -urN apr-1.0.1.orig/file_io/unix/pipe.c apr-1.0.1/file_io/unix/pipe.c --- apr-1.0.1.orig/file_io/unix/pipe.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/file_io/unix/pipe.c 2004-12-17 15:19:11.000000000 +0100 @@ -42,7 +42,7 @@ fd_flags &= ~O_NONBLOCK; # elif defined(O_NDELAY) fd_flags &= ~O_NDELAY; -# elif defined(FNDELAY) +# elif defined(O_FNDELAY) fd_flags &= ~O_FNDELAY; # else /* XXXX: this breaks things, but an alternative isn't obvious...*/ @@ -77,7 +77,7 @@ fd_flags |= O_NONBLOCK; # elif defined(O_NDELAY) fd_flags |= O_NDELAY; -# elif defined(FNDELAY) +# elif defined(O_FNDELAY) fd_flags |= O_FNDELAY; # else /* XXXX: this breaks things, but an alternative isn't obvious...*/ diff -urN apr-1.0.1.orig/include/apr.h.in apr-1.0.1/include/apr.h.in --- apr-1.0.1.orig/include/apr.h.in 2004-06-05 13:52:43.000000000 +0200 +++ apr-1.0.1/include/apr.h.in 2004-12-17 15:19:10.000000000 +0100 @@ -172,12 +172,14 @@ #define APR_USE_FCNTL_SERIALIZE @fcntlser@ #define APR_USE_PROC_PTHREAD_SERIALIZE @procpthreadser@ #define APR_USE_PTHREAD_SERIALIZE @pthreadser@ +#define APR_USE_BEOS_SEM_SERIALIZE @beossemser@ #define APR_HAS_FLOCK_SERIALIZE @hasflockser@ #define APR_HAS_SYSVSEM_SERIALIZE @hassysvser@ #define APR_HAS_POSIXSEM_SERIALIZE @hasposixser@ #define APR_HAS_FCNTL_SERIALIZE @hasfcntlser@ #define APR_HAS_PROC_PTHREAD_SERIALIZE @hasprocpthreadser@ +#define APR_HAS_BEOS_SEM_SERIALIZE @hasbeossemser@ #define APR_PROCESS_LOCK_IS_GLOBAL @proclockglobal@ diff -urN apr-1.0.1.orig/include/apr_portable.h apr-1.0.1/include/apr_portable.h --- apr-1.0.1.orig/include/apr_portable.h 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/include/apr_portable.h 2004-12-17 15:19:10.000000000 +0100 @@ -87,9 +87,24 @@ #include #include +/** Basic OS process mutex structure. */ struct apr_os_proc_mutex_t { - sem_id sem; - int32 ben; +#if APR_HAS_SYSVSEM_SERIALIZE || APR_HAS_FCNTL_SERIALIZE || APR_HAS_FLOCK_SERIALIZE + /** Value used for SYS V Semaphore, FCNTL and FLOCK serialization */ + int crossproc; +#endif +#if APR_HAS_PROC_PTHREAD_SERIALIZE + /** Value used for PTHREAD serialization */ + pthread_mutex_t *pthread_interproc; +#endif +#if APR_HAS_THREADS + /* If no threads, no need for thread locks */ +#if APR_USE_PTHREAD_SERIALIZE + /** This value is currently unused within APR and Apache */ + pthread_mutex_t *intraproc; +#endif + sem_id beos_sem; +#endif }; typedef int apr_os_file_t; @@ -98,7 +113,7 @@ typedef struct apr_os_proc_mutex_t apr_os_proc_mutex_t; typedef thread_id apr_os_thread_t; typedef thread_id apr_os_proc_t; -typedef int apr_os_threadkey_t; +typedef int32 apr_os_threadkey_t; typedef struct timeval apr_os_imp_time_t; typedef struct tm apr_os_exp_time_t; typedef image_id apr_os_dso_handle_t; --- apr-1.0.1.orig/include/arch/beos/apr_arch_proc_mutex.h 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/include/arch/beos/apr_arch_proc_mutex.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,35 +0,0 @@ -/* Copyright 2000-2004 The Apache Software Foundation - * - * Licensed 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. - */ - -#ifndef PROC_MUTEX_H -#define PROC_MUTEX_H - -#include "apr_pools.h" -#include "apr_proc_mutex.h" -#include "apr_file_io.h" -#include "apr_general.h" -#include "apr_lib.h" -#include "apr_portable.h" - -struct apr_proc_mutex_t { - apr_pool_t *pool; - - /* Our lock :) */ - sem_id Lock; - int32 LockCount; -}; - -#endif /* PROC_MUTEX_H */ - diff -urN apr-1.0.1.orig/include/arch/beos/apr_arch_shm.h apr-1.0.1/include/arch/beos/apr_arch_shm.h --- apr-1.0.1.orig/include/arch/beos/apr_arch_shm.h 1970-01-01 01:00:00.000000000 +0100 +++ apr-1.0.1/include/arch/beos/apr_arch_shm.h 2004-12-17 15:19:11.000000000 +0100 @@ -0,0 +1,35 @@ +/* Copyright 2000-2004 The Apache Software Foundation + * + * Licensed 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. + */ + +#ifndef SHM_H +#define SHM_H + +#include +#include "apr_pools.h" +#include "apr_general.h" +#include "apr_lib.h" +#include "apr_portable.h" + +typedef struct beos_area_handle beos_area_handle; + +struct apr_shm_t { + apr_pool_t *pool; + beos_area_handle *handle; +}; + +apr_status_t apr_beos_setup_shmem(); +apr_status_t apr_beos_shmem_child_init(); + +#endif /* SHM_H */ diff -urN apr-1.0.1.orig/include/arch/beos/apr_arch_thread_mutex.h apr-1.0.1/include/arch/beos/apr_arch_thread_mutex.h --- apr-1.0.1.orig/include/arch/beos/apr_arch_thread_mutex.h 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/include/arch/beos/apr_arch_thread_mutex.h 2004-12-17 15:19:11.000000000 +0100 @@ -37,5 +37,8 @@ int owner_ref; }; +apr_status_t apr_beos_thread_mutex_init(apr_thread_mutex_t *mutex, + unsigned int flags, apr_pool_t *pool); + #endif /* THREAD_MUTEX_H */ diff -urN apr-1.0.1.orig/include/arch/beos/apr_arch_threadproc.h apr-1.0.1/include/arch/beos/apr_arch_threadproc.h --- apr-1.0.1.orig/include/arch/beos/apr_arch_threadproc.h 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/include/arch/beos/apr_arch_threadproc.h 2004-12-17 15:19:11.000000000 +0100 @@ -44,6 +44,7 @@ void *data; apr_thread_start_t func; apr_status_t exitval; + vint32 join_count; }; struct apr_threadattr_t { @@ -55,21 +56,8 @@ struct apr_threadkey_t { apr_pool_t *pool; - int32 key; -}; - -struct beos_private_data { - const void ** data; - int count; - volatile thread_id td; -}; - -struct beos_key { - int assigned; - int count; - sem_id lock; - int32 ben_lock; - void (* destructor) (void *); + int32 key; + void (*destructor)(void *); }; struct apr_procattr_t { @@ -87,7 +75,6 @@ struct apr_thread_once_t { sem_id sem; - int hit; }; #endif /* ! THREAD_PROC_H */ diff -urN apr-1.0.1.orig/include/arch/unix/apr_arch_proc_mutex.h apr-1.0.1/include/arch/unix/apr_arch_proc_mutex.h --- apr-1.0.1.orig/include/arch/unix/apr_arch_proc_mutex.h 2004-06-14 10:53:31.000000000 +0200 +++ apr-1.0.1/include/arch/unix/apr_arch_proc_mutex.h 2004-12-17 15:19:10.000000000 +0100 @@ -104,6 +104,9 @@ #if APR_HAS_PROC_PTHREAD_SERIALIZE pthread_mutex_t *pthread_interproc; #endif +#if APR_HAS_BEOS_SEM_SERIALIZE + sem_id beos_sem; +#endif }; void apr_proc_mutex_unix_setup_lock(void); diff -urN apr-1.0.1.orig/locks/beos/locks_common.c apr-1.0.1/locks/beos/locks_common.c --- apr-1.0.1.orig/locks/beos/locks_common.c 1970-01-01 01:00:00.000000000 +0100 +++ apr-1.0.1/locks/beos/locks_common.c 2004-12-17 15:19:11.000000000 +0100 @@ -0,0 +1,5 @@ +/* Include "apr_arch_thread_mutex.h" first, so that "apr_arch_global_mutex.h" + * won't include the wrong one (the UNIX version). + */ +#include "apr_arch_thread_mutex.h" +#include "../unix/global_mutex.c" diff -urN apr-1.0.1.orig/locks/beos/proc_mutex.c apr-1.0.1/locks/beos/proc_mutex.c --- apr-1.0.1.orig/locks/beos/proc_mutex.c 2004-03-09 15:39:45.000000000 +0100 +++ apr-1.0.1/locks/beos/proc_mutex.c 2004-12-17 15:19:11.000000000 +0100 @@ -13,157 +13,68 @@ * limitations under the License. */ -/*Read/Write locking implementation based on the MultiLock code from - * Stephen Beaulieu - */ - #include "apr_arch_proc_mutex.h" #include "apr_strings.h" #include "apr_portable.h" +#if APR_HAS_FLOCK_SERIALIZE +#include +#endif -static apr_status_t _proc_mutex_cleanup(void * data) -{ - apr_proc_mutex_t *lock = (apr_proc_mutex_t*)data; - if (lock->LockCount != 0) { - /* we're still locked... */ - while (atomic_add(&lock->LockCount , -1) > 1){ - /* OK we had more than one person waiting on the lock so - * the sem is also locked. Release it until we have no more - * locks left. - */ - release_sem (lock->Lock); - } - } - delete_sem(lock->Lock); - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_proc_mutex_create(apr_proc_mutex_t **mutex, - const char *fname, - apr_lockmech_e mech, - apr_pool_t *pool) -{ - apr_proc_mutex_t *new; - apr_status_t stat = APR_SUCCESS; - - if (mech != APR_LOCK_DEFAULT) { - return APR_ENOTIMPL; - } - - new = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); - if (new == NULL){ - return APR_ENOMEM; - } - - if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) { - _proc_mutex_cleanup(new); - return stat; - } - new->LockCount = 0; - new->Lock = stat; - new->pool = pool; - - apr_pool_cleanup_register(new->pool, (void *)new, _proc_mutex_cleanup, - apr_pool_cleanup_null); - - (*mutex) = new; - return APR_SUCCESS; -} +#include -APR_DECLARE(apr_status_t) apr_proc_mutex_child_init(apr_proc_mutex_t **mutex, - const char *fname, - apr_pool_t *pool) +static apr_status_t proc_mutex_beos_sem_cleanup(void *mutex_) { - return APR_SUCCESS; -} + apr_proc_mutex_t *mutex = mutex_; -APR_DECLARE(apr_status_t) apr_proc_mutex_lock(apr_proc_mutex_t *mutex) -{ - int32 stat; - - if (atomic_add(&mutex->LockCount, 1) > 0) { - if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) { - atomic_add(&mutex->LockCount, -1); - return stat; - } - } - return APR_SUCCESS; -} - -APR_DECLARE(apr_status_t) apr_proc_mutex_trylock(apr_proc_mutex_t *mutex) -{ - return APR_ENOTIMPL; -} + return delete_sem(mutex->beos_sem); +} -APR_DECLARE(apr_status_t) apr_proc_mutex_unlock(apr_proc_mutex_t *mutex) +static apr_status_t proc_mutex_beos_sem_create(apr_proc_mutex_t *new_mutex, + const char *fname) { - int32 stat; - - if (atomic_add(&mutex->LockCount, -1) > 1) { - if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) { - atomic_add(&mutex->LockCount, 1); - return stat; - } - } - return APR_SUCCESS; -} + new_mutex->beos_sem = create_sem(1, "APR_ProcMutex"); + if (new_mutex->beos_sem < B_NO_ERROR) + return new_mutex->beos_sem; -APR_DECLARE(apr_status_t) apr_proc_mutex_destroy(apr_proc_mutex_t *mutex) -{ - apr_status_t stat; - if ((stat = _proc_mutex_cleanup(mutex)) == APR_SUCCESS) { - apr_pool_cleanup_kill(mutex->pool, mutex, _proc_mutex_cleanup); - return APR_SUCCESS; - } - return stat; -} + apr_pool_cleanup_register(new_mutex->pool, (void *)new_mutex, + apr_proc_mutex_cleanup, + apr_pool_cleanup_null); -APR_DECLARE(apr_status_t) apr_proc_mutex_cleanup(void *mutex) -{ - return _proc_mutex_cleanup(mutex); + return APR_SUCCESS; } - -APR_DECLARE(const char *) apr_proc_mutex_lockfile(apr_proc_mutex_t *mutex) +static apr_status_t proc_mutex_beos_sem_acquire(apr_proc_mutex_t *mutex) { - return NULL; + return acquire_sem(mutex->beos_sem); } -APR_DECLARE(const char *) apr_proc_mutex_name(apr_proc_mutex_t *mutex) +static apr_status_t proc_mutex_beos_sem_tryacquire(apr_proc_mutex_t *mutex) { - return "beossem"; + return acquire_sem_etc(mutex->beos_sem, 0, B_RELATIVE_TIMEOUT, 0); } -APR_DECLARE(const char *) apr_proc_mutex_defname(void) +static apr_status_t proc_mutex_beos_sem_release(apr_proc_mutex_t *mutex) { - return "beossem"; + return release_sem(mutex->beos_sem); } -APR_POOL_IMPLEMENT_ACCESSOR(proc_mutex) - -/* Implement OS-specific accessors defined in apr_portable.h */ - -APR_DECLARE(apr_status_t) apr_os_proc_mutex_get(apr_os_proc_mutex_t *ospmutex, - apr_proc_mutex_t *pmutex) +static apr_status_t proc_mutex_beos_sem_child_init(apr_proc_mutex_t **mutex, + apr_pool_t *cont, + const char *fname) { - ospmutex->sem = pmutex->Lock; - ospmutex->ben = pmutex->LockCount; return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_os_proc_mutex_put(apr_proc_mutex_t **pmutex, - apr_os_proc_mutex_t *ospmutex, - apr_pool_t *pool) -{ - if (pool == NULL) { - return APR_ENOPOOL; - } - if ((*pmutex) == NULL) { - (*pmutex) = (apr_proc_mutex_t *)apr_pcalloc(pool, sizeof(apr_proc_mutex_t)); - (*pmutex)->pool = pool; - } - (*pmutex)->Lock = ospmutex->sem; - (*pmutex)->LockCount = ospmutex->ben; - return APR_SUCCESS; -} +static const apr_proc_mutex_unix_lock_methods_t mutex_beos_sem_methods = +{ + APR_PROCESS_LOCK_MECH_IS_GLOBAL, + proc_mutex_beos_sem_create, + proc_mutex_beos_sem_acquire, + proc_mutex_beos_sem_tryacquire, + proc_mutex_beos_sem_release, + proc_mutex_beos_sem_cleanup, + proc_mutex_beos_sem_child_init, + "beossem" +}; +#include "../unix/proc_mutex.c" diff -urN apr-1.0.1.orig/locks/beos/thread_cond.c apr-1.0.1/locks/beos/thread_cond.c --- apr-1.0.1.orig/locks/beos/thread_cond.c 2004-02-26 18:03:26.000000000 +0100 +++ apr-1.0.1/locks/beos/thread_cond.c 2004-12-17 15:19:11.000000000 +0100 @@ -20,7 +20,6 @@ static apr_status_t thread_cond_cleanup(void *data) { - struct waiter *w; apr_thread_cond_t *cond = (apr_thread_cond_t *)data; acquire_sem(cond->lock); diff -urN apr-1.0.1.orig/locks/beos/thread_mutex.c apr-1.0.1/locks/beos/thread_mutex.c --- apr-1.0.1.orig/locks/beos/thread_mutex.c 2004-02-26 18:03:26.000000000 +0100 +++ apr-1.0.1/locks/beos/thread_mutex.c 2004-12-17 15:19:11.000000000 +0100 @@ -26,18 +26,37 @@ apr_thread_mutex_t *lock = (apr_thread_mutex_t*)data; if (lock->LockCount != 0) { /* we're still locked... */ - while (atomic_add(&lock->LockCount , -1) > 1){ - /* OK we had more than one person waiting on the lock so - * the sem is also locked. Release it until we have no more - * locks left. - */ + while (atomic_add(&lock->LockCount , -1) > 1){ + /* OK we had more than one person waiting on the lock so + * the sem is also locked. Release it until we have no more + * locks left. + */ release_sem (lock->Lock); - } + } } delete_sem(lock->Lock); return APR_SUCCESS; } +/* pool may be NULL. */ +apr_status_t apr_beos_thread_mutex_init(apr_thread_mutex_t *mutex, + unsigned int flags, apr_pool_t *pool) +{ + mutex->Lock = create_sem(0, "APR_Lock"); + if (mutex->Lock < 0) + return mutex->Lock; + + mutex->LockCount = 0; + mutex->pool = pool; + + /* Optimal default is APR_THREAD_MUTEX_UNNESTED, + * no additional checks required for either flag. + */ + mutex->nested = flags & APR_THREAD_MUTEX_NESTED; + + return APR_SUCCESS; +} + APR_DECLARE(apr_status_t) apr_thread_mutex_create(apr_thread_mutex_t **mutex, unsigned int flags, apr_pool_t *pool) @@ -49,19 +68,10 @@ if (new_m == NULL){ return APR_ENOMEM; } - - if ((stat = create_sem(0, "APR_Lock")) < B_NO_ERROR) { - _thread_mutex_cleanup(new_m); - return stat; - } - new_m->LockCount = 0; - new_m->Lock = stat; - new_m->pool = pool; - /* Optimal default is APR_THREAD_MUTEX_UNNESTED, - * no additional checks required for either flag. - */ - new_m->nested = flags & APR_THREAD_MUTEX_NESTED; + stat = apr_beos_thread_mutex_init(new_m, flags, pool); + if (stat != APR_SUCCESS) + return stat; apr_pool_cleanup_register(new_m->pool, (void *)new_m, _thread_mutex_cleanup, apr_pool_cleanup_null); @@ -90,13 +100,13 @@ return APR_SUCCESS; } - if (atomic_add(&mutex->LockCount, 1) > 0) { - if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) { + if (atomic_add(&mutex->LockCount, 1) > 0) { + if ((stat = acquire_sem(mutex->Lock)) < B_NO_ERROR) { /* Oh dear, acquire_sem failed!! */ - atomic_add(&mutex->LockCount, -1); - return stat; - } - } + atomic_add(&mutex->LockCount, -1); + return stat; + } + } mutex->owner = me; mutex->owner_ref = 1; @@ -119,7 +129,7 @@ return APR_SUCCESS; } - if (atomic_add(&mutex->LockCount, -1) > 1) { + if (atomic_add(&mutex->LockCount, -1) > 1) { if ((stat = release_sem(mutex->Lock)) < B_NO_ERROR) { atomic_add(&mutex->LockCount, 1); return stat; diff -urN apr-1.0.1.orig/locks/unix/proc_mutex.c apr-1.0.1/locks/unix/proc_mutex.c --- apr-1.0.1.orig/locks/unix/proc_mutex.c 2004-06-15 10:21:22.000000000 +0200 +++ apr-1.0.1/locks/unix/proc_mutex.c 2004-12-17 15:19:11.000000000 +0100 @@ -717,6 +717,8 @@ new_mutex->inter_meth = &mutex_proc_pthread_methods; #elif APR_USE_POSIXSEM_SERIALIZE new_mutex->inter_meth = &mutex_posixsem_methods; +#elif APR_USE_BEOS_SEM_SERIALIZE + new_mutex->inter_meth = &mutex_beos_sem_methods; #else return APR_ENOTIMPL; #endif @@ -837,6 +839,9 @@ #if APR_HAS_PROC_PTHREAD_SERIALIZE ospmutex->pthread_interproc = pmutex->pthread_interproc; #endif +#if APR_HAS_BEOS_SEM_SERIALIZE + ospmutex->beos_sem = pmutex->beos_sem; +#endif return APR_SUCCESS; } @@ -858,6 +863,9 @@ #if APR_HAS_PROC_PTHREAD_SERIALIZE (*pmutex)->pthread_interproc = ospmutex->pthread_interproc; #endif +#if APR_HAS_BEOS_SEM_SERIALIZE + (*pmutex)->beos_sem = ospmutex->beos_sem; +#endif return APR_SUCCESS; } diff -urN apr-1.0.1.orig/misc/unix/start.c apr-1.0.1/misc/unix/start.c --- apr-1.0.1.orig/misc/unix/start.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/misc/unix/start.c 2004-12-17 15:19:11.000000000 +0100 @@ -22,6 +22,10 @@ #include "apr_arch_proc_mutex.h" /* for apr_proc_mutex_unix_setup_lock() */ #include "apr_arch_internal_time.h" +#ifdef BEOS +#include "apr_arch_shm.h" /* for apr_beos_setup_shmem() */ +#endif + APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, const char * const * *argv, @@ -51,6 +55,10 @@ apr_unix_setup_time(); #endif +#ifdef BEOS + apr_beos_setup_shmem(); +#endif + if ((status = apr_pool_initialize()) != APR_SUCCESS) return status; --- apr-1.0.1.orig/network_io/beos/sendrecv.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/network_io/beos/sendrecv.c 2004-12-17 15:25:26.000000000 +0100 @@ -17,9 +17,14 @@ #if BEOS_BONE /* BONE uses the unix code - woohoo */ #include "../unix/sendrecv.c" #else +#include + #include "apr_arch_networkio.h" #include "apr_time.h" +#define SEND_WAIT APR_USEC_PER_SEC / 100 +#define RECEIVE_WAIT APR_USEC_PER_SEC / 100 + static apr_status_t wait_for_io_or_timeout(apr_socket_t *sock, int for_read) { struct timeval tv, *tvptr; @@ -37,6 +42,8 @@ tv.tv_usec = sock->timeout % APR_USEC_PER_SEC; tvptr = &tv; } + /* This probably only works for read_for. At least according to the + * documentation only the read set argument is actually supported. */ srv = select(sock->socketdes + 1, for_read ? &fdset : NULL, for_read ? NULL : &fdset, @@ -54,38 +61,46 @@ return APR_SUCCESS; } -#define SEND_WAIT APR_USEC_PER_SEC / 10 +apr_status_t apr_wait_for_io_or_timeout(apr_file_t *f, apr_socket_t *s, + int for_read) +{ + /* BeOS net_server select() supports sockets only */ + if (!f) + return APR_ENOTIMPL; + + return wait_for_io_or_timeout(s, for_read); +} APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, apr_size_t *len) { apr_ssize_t rv; - + do { rv = send(sock->socketdes, buf, (*len), 0); } while (rv == -1 && errno == EINTR); if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { - apr_int32_t snooze_val = SEND_WAIT; - apr_int32_t zzz = 0; - - do { - rv = send(sock->socketdes, buf, (*len), 0); - if (rv == -1 && errno == EWOULDBLOCK){ - apr_sleep (snooze_val); - zzz += snooze_val; - snooze_val += SEND_WAIT; - /* have we passed our timeout value */ - if (zzz > (sock->timeout * APR_USEC_PER_SEC)) - break; - } - } while (rv == -1 && (errno == EINTR || errno == EWOULDBLOCK)); + bigtime_t now = system_time(); + bigtime_t endTime = now + sock->timeout; + while (now < endTime) { + snooze(RECEIVE_WAIT); + + do { + rv = send(sock->socketdes, buf, (*len), 0); + } while (rv == -1 && errno == EINTR); + + if (rv >= 0 || (rv < 0 && errno != EWOULDBLOCK)) + break; + + now = system_time(); + }; } if (rv == -1) { *len = 0; - return errno; + return (errno == EWOULDBLOCK ? APR_TIMEUP : errno); } - (*len) = rv; + *len = rv; return APR_SUCCESS; } @@ -100,22 +115,30 @@ } while (rv == -1 && errno == EINTR); if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 1); - if (arv != APR_SUCCESS) { - *len = 0; - return arv; - } - else { + /* bonefish: I don't know why, but in some cases select() seems to + * return success, even if there's nothing to read yet. Maybe if the + * connection is not yet established? The tests exposed this problem. + * Long story short, we have to poll here, too. */ + bigtime_t now = system_time(); + bigtime_t endTime = now + sock->timeout; + while (now < endTime) { + snooze(RECEIVE_WAIT); + do { rv = recv(sock->socketdes, buf, (*len), 0); } while (rv == -1 && errno == EINTR); - } + + if (rv >= 0 || (rv < 0 && errno != EWOULDBLOCK)) + break; + + now = system_time(); + }; } if (rv == -1) { (*len) = 0; - return errno; + return (errno == EWOULDBLOCK ? APR_TIMEUP : errno); } - (*len) = rv; + *len = rv; if (rv == 0) return APR_EOF; return APR_SUCCESS; @@ -144,23 +167,28 @@ where->salen); } while (rv == -1 && errno == EINTR); - if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) - && sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 0); - if (arv != APR_SUCCESS) { - *len = 0; - return arv; - } else { + + if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { + bigtime_t now = system_time(); + bigtime_t endTime = now + sock->timeout; + while (now < endTime) { + snooze(RECEIVE_WAIT); + do { rv = sendto(sock->socketdes, buf, (*len), flags, (const struct sockaddr*)&where->sa, where->salen); } while (rv == -1 && errno == EINTR); - } + + if (rv >= 0 || (rv < 0 && errno != EWOULDBLOCK)) + break; + + now = system_time(); + }; } if (rv == -1) { *len = 0; - return errno; + return (errno == EWOULDBLOCK ? APR_TIMEUP : errno); } *len = rv; return APR_SUCCESS; @@ -173,38 +201,38 @@ { apr_ssize_t rv; - if (from == NULL){ - return APR_ENOMEM; - /* Not sure if this is correct. Maybe we should just allocate - the memory?? - */ - } - do { rv = recvfrom(sock->socketdes, buf, (*len), flags, (struct sockaddr*)&from->sa, &from->salen); } while (rv == -1 && errno == EINTR); - if (rv == -1 && (errno == EAGAIN || errno == EWOULDBLOCK) && - sock->timeout != 0) { - apr_status_t arv = wait_for_io_or_timeout(sock, 1); - if (arv != APR_SUCCESS) { - *len = 0; - return arv; - } else { + if (rv == -1 && errno == EWOULDBLOCK && sock->timeout > 0) { + /* bonefish: I don't know why, but in some cases select() seems to + * return success, even if there's nothing to read yet. Maybe if the + * connection is not yet established? The tests exposed this problem. + * Long story short, we have to poll here, too. */ + bigtime_t now = system_time(); + bigtime_t endTime = now + sock->timeout; + while (now < endTime) { + snooze(RECEIVE_WAIT); + do { rv = recvfrom(sock->socketdes, buf, (*len), flags, (struct sockaddr*)&from->sa, &from->salen); - } while (rv == -1 && errno == EINTR); - } + } while (rv == -1 && errno == EINTR); + + if (rv >= 0 || (rv < 0 && errno != EWOULDBLOCK)) + break; + + now = system_time(); + }; } if (rv == -1) { (*len) = 0; - return errno; + return (errno == EWOULDBLOCK ? APR_TIMEUP : errno); } - - (*len) = rv; - if (rv == 0) + *len = rv; + if (rv == 0 && sock->type == SOCK_STREAM) return APR_EOF; return APR_SUCCESS; diff -urN apr-1.0.1.orig/network_io/unix/sockaddr.c apr-1.0.1/network_io/unix/sockaddr.c --- apr-1.0.1.orig/network_io/unix/sockaddr.c 2004-07-13 11:15:50.000000000 +0200 +++ apr-1.0.1/network_io/unix/sockaddr.c 2004-12-17 15:19:11.000000000 +0100 @@ -543,7 +543,7 @@ if ((masked = flags & (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK))) { if (!hostname || - family != AF_UNSPEC || + family != APR_UNSPEC || masked == (APR_IPV4_ADDR_OK | APR_IPV6_ADDR_OK)) { return APR_EINVAL; } diff -urN apr-1.0.1.orig/network_io/unix/sockets.c apr-1.0.1/network_io/unix/sockets.c --- apr-1.0.1.orig/network_io/unix/sockets.c 2004-03-10 21:58:34.000000000 +0100 +++ apr-1.0.1/network_io/unix/sockets.c 2004-12-17 15:19:11.000000000 +0100 @@ -20,9 +20,10 @@ #include "apr_portable.h" #include "apr_arch_inherit.h" -#if defined(BEOS) && !defined(BEOS_BONE) +#ifdef BEOS_R5 +#undef close #define close closesocket -#endif +#endif /* BEOS_R5 */ static char generic_inaddr_any[16] = {0}; /* big enough for IPv4 or IPv6 */ @@ -92,7 +93,28 @@ alloc_socket(new, cont); +#ifndef BEOS_R5 (*new)->socketdes = socket(family, type, protocol); +#else + /* For any reason BeOS R5 has an unconventional protocol numbering, + * so we need to translate here. */ + switch (protocol) { + case 0: + (*new)->socketdes = socket(family, type, 0); + break; + case APR_PROTO_TCP: + (*new)->socketdes = socket(family, type, IPPROTO_TCP); + break; + case APR_PROTO_UDP: + (*new)->socketdes = socket(family, type, IPPROTO_UDP); + break; + case APR_PROTO_SCTP: + default: + errno = EPROTONOSUPPORT; + (*new)->socketdes = -1; + break; + } +#endif /* BEOS_R5 */ #if APR_HAVE_IPV6 if ((*new)->socketdes < 0 && ofamily == APR_UNSPEC) { diff -urN apr-1.0.1.orig/network_io/unix/sockopt.c apr-1.0.1/network_io/unix/sockopt.c --- apr-1.0.1.orig/network_io/unix/sockopt.c 2004-04-03 19:15:52.000000000 +0200 +++ apr-1.0.1/network_io/unix/sockopt.c 2004-12-17 15:19:11.000000000 +0100 @@ -323,6 +323,7 @@ apr_status_t apr_socket_atmark(apr_socket_t *sock, int *atmark) { +#ifndef BEOS_R5 int oobmark; if (ioctl(sock->socketdes, SIOCATMARK, (void*) &oobmark) < 0) @@ -331,6 +332,9 @@ *atmark = (oobmark != 0); return APR_SUCCESS; +#else + return APR_ENOTIMPL; +#endif } diff -urN apr-1.0.1.orig/shmem/beos/shm.c apr-1.0.1/shmem/beos/shm.c --- apr-1.0.1.orig/shmem/beos/shm.c 2004-06-29 18:38:16.000000000 +0200 +++ apr-1.0.1/shmem/beos/shm.c 2004-12-17 15:19:11.000000000 +0100 @@ -13,25 +13,147 @@ * limitations under the License. */ -#include "apr_general.h" -#include "apr_shm.h" +#include "apr_arch_shm.h" +#include "apr_arch_thread_mutex.h" #include "apr_errno.h" #include "apr_lib.h" +#include "apr_general.h" +#include "apr_portable.h" +#include "apr_ring.h" +#include "apr_shm.h" #include "apr_strings.h" + +#include #include #include -#include -#include "apr_portable.h" +#include + +#include + +static struct apr_thread_mutex_t area_handles_lock; -struct apr_shm_t { - apr_pool_t *pool; - void *memblock; - void *ptr; - apr_size_t reqsize; - apr_size_t avail; - area_id aid; +APR_RING_HEAD(area_handle_list, beos_area_handle); +static struct area_handle_list area_handles; + +struct beos_area_handle { + APR_RING_ENTRY(beos_area_handle) link; + area_id id; /* area id */ + char *name; /* area name */ + void *address; /* base address */ + apr_size_t size; /* requested size */ + char *filename; /* name of the file, associated with the area */ + int fd; /* FD of the file, associated with the area */ + int use_count; /* how often attached in this process */ }; +typedef struct shmem_file_info { + apr_size_t size; /* requested size of the shmem */ + char name[B_OS_NAME_LENGTH]; /* area name */ +} shmem_file_info; + +#define LOCK_AREA_HANDLES() apr_thread_mutex_lock(&area_handles_lock) +#define UNLOCK_AREA_HANDLES() apr_thread_mutex_unlock(\ + &area_handles_lock) +#define INIT_AREA_HANDLE_LINK(handle) APR_RING_ELEM_INIT(handle, link) +#define FIRST_AREA_HANDLE() APR_RING_FIRST(&area_handles) +#define NEXT_AREA_HANDLE(handle) APR_RING_NEXT(handle, link) +#define AREA_HANDLES_END() APR_RING_SENTINEL(&area_handles, \ + beos_area_handle, link) +#define ADD_AREA_HANDLE(handle) APR_RING_INSERT_TAIL(&area_handles, \ + handle, \ + beos_area_handle, \ + link) +#define REMOVE_AREA_HANDLE(handle) APR_RING_REMOVE(handle, link) + +/* Initializes the area handle list and the semaphore that protects it. Invoked + by apr_initialize(). */ +apr_status_t apr_beos_setup_shmem() +{ + APR_RING_INIT(&area_handles, beos_area_handle, link); + return apr_beos_thread_mutex_init(&area_handles_lock, 0, NULL); +} + +/* Called directly after fork() in the child process. Sets up the semaphore + that protects the area handle list in a child process and repairs the shared + memory areas. The problem is that BeOS fork() clones all areas copy on write, + which requires us to re-clone the parent's areas. */ +apr_status_t apr_beos_shmem_child_init() +{ + apr_status_t error; + beos_area_handle *handle; + + /* re-init the lock */ + error = apr_beos_thread_mutex_init(&area_handles_lock, 0, NULL); + if (error != B_OK) + return error; + + /* now iterate through the area handle list and clone all areas */ + for (handle = FIRST_AREA_HANDLE(); + handle != AREA_HANDLES_END(); + handle = NEXT_AREA_HANDLE(handle)) { + /* delete the clone area and clone the original one */ + delete_area(area_for(handle->address)); + handle->id = clone_area(handle->name, &(handle->address), + B_EXACT_ADDRESS, B_READ_AREA | B_WRITE_AREA, + handle->id); + if (handle->id < 0) + return handle->id; + } + + return APR_SUCCESS; +} + +/* Creates a new area handle from a given valid area_info. */ +static beos_area_handle *create_area_handle(area_id id, const char *name, + void *address, apr_size_t size, + const char *filename, int fd, + int useCount) +{ + beos_area_handle *handle + = (beos_area_handle*)malloc(sizeof(beos_area_handle)); + if (!handle) + return NULL; + + INIT_AREA_HANDLE_LINK(handle); + handle->id = id; + handle->name = strdup(name); + handle->address = address; + handle->size = size; + handle->filename = (filename ? strdup(filename) : NULL); + handle->fd = fd; + handle->use_count = useCount; + + if (!handle->name || (filename && !handle->filename)) { + free(handle->name); + free(handle->filename); + free(handle); + return NULL; + } + + return handle; +} + +static apr_status_t shm_cleanup(void *_m) +{ + apr_shm_t *m = (apr_shm_t*)_m; + + LOCK_AREA_HANDLES(); + + if (m->handle && --m->handle->use_count == 0) { + REMOVE_AREA_HANDLE(m->handle); + delete_area(m->handle->id); + if (m->handle->fd >= 0) + close(m->handle->fd); + free(m->handle->name); + free(m->handle); + } + m->handle = NULL; + + UNLOCK_AREA_HANDLES(); + + return APR_SUCCESS; +} + APR_DECLARE(apr_status_t) apr_shm_create(apr_shm_t **m, apr_size_t reqsize, const char *filename, @@ -40,53 +162,102 @@ apr_size_t pagesize; area_id newid; char *addr; - char shname[B_OS_NAME_LENGTH]; + shmem_file_info fileInfo; + char *shname = fileInfo.name; + int fd = -1; + int num = 0; + status_t error = B_OK; + beos_area_handle *handle = NULL; (*m) = (apr_shm_t *)apr_pcalloc(p, sizeof(apr_shm_t)); /* we MUST allocate in pages, so calculate how big an area we need... */ pagesize = ((reqsize + B_PAGE_SIZE - 1) / B_PAGE_SIZE) * B_PAGE_SIZE; - - if (!filename) { - int num = 0; - snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld", find_thread(NULL)); - while (find_area(shname) >= 0) - snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld_%d", - find_thread(NULL), num++); - } - newid = create_area(filename ? filename : shname, - (void*)&addr, B_ANY_ADDRESS, - pagesize, B_LAZY_LOCK, B_READ_AREA|B_WRITE_AREA); - if (newid < 0) - return errno; + + /* create a unique name for the area */ + snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld", find_thread(NULL)); + while (find_area(shname) >= 0) + snprintf(shname, B_OS_NAME_LENGTH, "apr_shmem_%ld_%d", + find_thread(NULL), num++); + + LOCK_AREA_HANDLES(); + + /* if a file name was given, create the file */ + if (filename) { + fd = open(filename, O_RDWR |O_CREAT | O_TRUNC | O_EXCL, + S_IRUSR | S_IWUSR, S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); + if (fd < 0) + return errno; + } + + /* write the shmem info to the file */ + if (fd >= 0) { + int len = (shname + strlen(shname)) - (char*)&fileInfo; + fileInfo.size = reqsize; + if (write(fd, &fileInfo, len) < 0) + error = errno; + } + + /* allocate the area */ + if (error == B_OK) { + newid = create_area(shname, (void*)&addr, B_ANY_ADDRESS, + pagesize, B_LAZY_LOCK, B_READ_AREA | B_WRITE_AREA); + if (newid < 0) + error = newid; + } + + /* allocate an area handle */ + if (error == B_OK) { + handle = create_area_handle(newid, shname, addr, reqsize, filename, fd, + 1); + /* add it to the list */ + if (handle) + ADD_AREA_HANDLE(handle); + else + error = APR_ENOMEM; + } + + UNLOCK_AREA_HANDLES(); + + /* cleanup on error */ + if (error != B_OK) { + if (newid >= 0) + delete_area(newid); + if (filename) + unlink(filename); + close(fd); + return error; + } (*m)->pool = p; - (*m)->aid = newid; - (*m)->memblock = addr; - (*m)->ptr = (void*)addr; - (*m)->avail = pagesize; /* record how big an area we actually created... */ - (*m)->reqsize = reqsize; + (*m)->handle = handle; + + apr_pool_cleanup_register(p, *m, shm_cleanup, apr_pool_cleanup_null); return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_shm_destroy(apr_shm_t *m) { - delete_area(m->aid); - m->avail = 0; - m->memblock = NULL; - return APR_SUCCESS; + LOCK_AREA_HANDLES(); + + if (m->handle && m->handle->filename) { + unlink(m->handle->filename); + free(m->handle->filename); + m->handle->filename = NULL; + } + + UNLOCK_AREA_HANDLES(); + + return apr_pool_cleanup_run(m->pool, m, shm_cleanup); } APR_DECLARE(apr_status_t) apr_shm_remove(const char *filename, apr_pool_t *pool) { - area_id deleteme = find_area(filename); - - if (deleteme == B_NAME_NOT_FOUND) - return APR_EINVAL; + if (unlink(filename) < 0) + return errno; - delete_area(deleteme); return APR_SUCCESS; } @@ -94,58 +265,132 @@ const char *filename, apr_pool_t *pool) { - area_info ai; - thread_info ti; - apr_shm_t *new_m; - area_id deleteme = find_area(filename); - - if (deleteme == B_NAME_NOT_FOUND) + int fd = -1; + shmem_file_info fileInfo; + char *areaName = fileInfo.name; + int fileInfoLen; + int nameLen = 0; + beos_area_handle *handle = NULL; + area_id id = -1; + status_t error = B_OK; + + /* open the file */ + fd = open(filename, O_RDONLY); + if (fd < 0) return APR_EINVAL; - new_m = (apr_shm_t*)apr_palloc(pool, sizeof(apr_shm_t*)); - if (new_m == NULL) - return APR_ENOMEM; - new_m->pool = pool; - - get_area_info(deleteme, &ai); - get_thread_info(find_thread(NULL), &ti); - - if (ti.team != ai.team) { - area_id narea; - - narea = clone_area(ai.name, &(ai.address), B_CLONE_ADDRESS, - B_READ_AREA|B_WRITE_AREA, ai.area); - - if (narea < B_OK) - return narea; - - get_area_info(narea, &ai); - new_m->aid = narea; - new_m->memblock = ai.address; - new_m->ptr = (void*)ai.address; - new_m->avail = ai.size; - new_m->reqsize = ai.size; + /* read the file info */ + fileInfoLen = read(fd, &fileInfo, sizeof(shmem_file_info) - 1); + if (fileInfoLen > 0) { + nameLen = (char*)&fileInfo + fileInfoLen - areaName; + if (nameLen > 0) { + areaName[nameLen] = '\0'; + nameLen = strlen(areaName); + } + } + if (nameLen <= 0) + error = APR_EINVAL; + + LOCK_AREA_HANDLES(); + + /* check, if we already know the area */ + if (error == B_OK) { + beos_area_handle *itHandle; + for (itHandle = FIRST_AREA_HANDLE(); + itHandle != AREA_HANDLES_END(); + itHandle = NEXT_AREA_HANDLE(itHandle)) { + if (strcmp(itHandle->name, areaName) == 0) { + /* OK, found */ + handle = itHandle; + close(fd); + fd = -1; + break; + } + } + } + + /* if we don't know the area yet, get it */ + if (error == B_OK && !handle) { + id = find_area(areaName); + if (id < 0) + error = APR_EINVAL; + } + + /* if we have no error till now, then there definitely exists an area */ + if (error == B_OK) { + /* allocate memory for the new shared memory handle */ + *m = (apr_shm_t*)apr_palloc(pool, sizeof(apr_shm_t*)); + if (!*m) + error = APR_ENOMEM; } - (*m) = new_m; + /* if we don't know the area yet, we clone it */ + if (error == B_OK && !handle) { + area_info areaInfo; + error = get_area_info(id, &areaInfo); + if (error == B_OK && areaInfo.size < fileInfo.size) { + /* something's fishy: the actual area size is less than the + * shmem region it is supposed to contain */ + error = APR_EINVAL; + } + if (error == B_OK) { + void *address; + id = clone_area(areaInfo.name, &address, B_ANY_ADDRESS, + B_READ_AREA | B_WRITE_AREA, areaInfo.area); + if (id >= 0) { + /* create the area */ + handle = create_area_handle(id, areaName, address, + fileInfo.size, filename, fd, 0); + /* The size we supply here is actually not the real size + * of the shared memory region, but is rounded up to a + * page size multiple. We could store the real size in + * the file. */ - return APR_SUCCESS; + /* add it to the list */ + if (handle) { + ADD_AREA_HANDLE(handle); + } + else { + delete_area(id); + error = APR_ENOMEM; + } + } + else + error = id; + } + } + + /* now we should have a handle -- nothing can go wrong anymore */ + if (error == B_OK) { + (*m)->pool = pool; + (*m)->handle = handle; + (*m)->handle->use_count++; + apr_pool_cleanup_register(pool, *m, shm_cleanup, apr_pool_cleanup_null); + } + + UNLOCK_AREA_HANDLES(); + + /* cleanup on error */ + if (error != B_OK) { + close(fd); + } + + return error; } APR_DECLARE(apr_status_t) apr_shm_detach(apr_shm_t *m) { - delete_area(m->aid); - return APR_SUCCESS; + return apr_pool_cleanup_run(m->pool, m, shm_cleanup); } APR_DECLARE(void *) apr_shm_baseaddr_get(const apr_shm_t *m) { - return m->memblock; + return (m->handle ? m->handle->address : NULL); } APR_DECLARE(apr_size_t) apr_shm_size_get(const apr_shm_t *m) { - return m->reqsize; + return (m->handle ? m->handle->size : 0); } APR_POOL_IMPLEMENT_ACCESSOR(shm) diff -urN apr-1.0.1.orig/test/Makefile.in apr-1.0.1/test/Makefile.in --- apr-1.0.1.orig/test/Makefile.in 2004-11-17 02:07:02.000000000 +0100 +++ apr-1.0.1/test/Makefile.in 2004-12-17 15:19:11.000000000 +0100 @@ -72,7 +72,7 @@ $(LIBTOOL) $(LTFLAGS) --mode=compile $(COMPILE) -prefer-pic -c $(srcdir)/mod_test.c && touch $@ mod_test.la: mod_test.slo $(LOCAL_LIBS) - $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` -avoid-version -module mod_test.lo $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ + $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` -avoid-version -module mod_test.lo $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ $(LOCAL_LIBS) $(ALL_LIBS) libmod_test.la: mod_test.slo $(LOCAL_LIBS) $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) -rpath `pwd` -avoid-version mod_test.lo $(LT_LDFLAGS) $(ALL_LDFLAGS) -o $@ $(LOCAL_LIBS) $(ALL_LIBS) diff -urN apr-1.0.1.orig/test/testdso.c apr-1.0.1/test/testdso.c --- apr-1.0.1.orig/test/testdso.c 2004-05-14 16:43:22.000000000 +0200 +++ apr-1.0.1/test/testdso.c 2004-12-17 15:19:11.000000000 +0100 @@ -77,9 +77,11 @@ ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); ABTS_PTR_NOTNULL(tc, func1); - function = (void (*)(char *))func1; - (*function)(teststr); - ABTS_STR_EQUAL(tc, "Hello - I'm a DSO!\n", teststr); + if (status == APR_SUCCESS) { + function = (void (*)(char *))func1; + (*function)(teststr); + ABTS_STR_EQUAL(tc, "Hello - I'm a DSO!\n", teststr); + } apr_dso_unload(h); } @@ -100,9 +102,11 @@ ABTS_ASSERT(tc, apr_dso_error(h, errstr, 256), APR_SUCCESS == status); ABTS_PTR_NOTNULL(tc, func1); - function = (int (*)(int))func1; - status = (*function)(5); - ABTS_INT_EQUAL(tc, 5, status); + if (status == APR_SUCCESS) { + function = (int (*)(int))func1; + status = (*function)(5); + ABTS_INT_EQUAL(tc, 5, status); + } apr_dso_unload(h); } diff -urN apr-1.0.1.orig/test/testpipe.c apr-1.0.1/test/testpipe.c --- apr-1.0.1.orig/test/testpipe.c 2004-05-14 16:43:22.000000000 +0200 +++ apr-1.0.1/test/testpipe.c 2004-12-17 15:19:11.000000000 +0100 @@ -23,6 +23,11 @@ #include "apr_thread_proc.h" #include "apr_strings.h" +/* BeOS doesn't offer non-blocking pipes */ +#if defined(BEOS) +# define BLOCKING_PIPE_ONLY +#endif + static apr_file_t *readp = NULL; static apr_file_t *writep = NULL; @@ -60,6 +65,10 @@ ABTS_PTR_NOTNULL(tc, readp); ABTS_PTR_NOTNULL(tc, writep); +#ifdef BLOCKING_PIPE_ONLY + (void)timeout; + ABTS_NOT_IMPL(tc, "no non-blocking pipe support"); +#else rv = apr_file_pipe_timeout_get(readp, &timeout); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_INT_EQUAL(tc, -1, timeout); @@ -70,6 +79,7 @@ rv = apr_file_pipe_timeout_get(readp, &timeout); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_INT_EQUAL(tc, apr_time_from_sec(1), timeout); +#endif } static void read_write(abts_case *tc, void *data) @@ -86,12 +96,16 @@ ABTS_PTR_NOTNULL(tc, readp); ABTS_PTR_NOTNULL(tc, writep); +#ifdef BLOCKING_PIPE_ONLY + ABTS_NOT_IMPL(tc, "no non-blocking pipe support"); +#else rv = apr_file_pipe_timeout_set(readp, apr_time_from_sec(1)); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); rv = apr_file_read(readp, buf, &nbytes); ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv)); ABTS_INT_EQUAL(tc, 0, nbytes); +#endif } static void read_write_notimeout(abts_case *tc, void *data) @@ -122,6 +136,9 @@ static void test_pipe_writefull(abts_case *tc, void *data) { +#ifdef BLOCKING_PIPE_ONLY + ABTS_NOT_IMPL(tc, "no non-blocking pipe support"); +#else int iterations = 1000; int i; int bytes_per_iteration = 8000; @@ -177,6 +194,7 @@ apr_proc_wait(&proc, NULL, &why, APR_WAIT) == APR_CHILD_DONE); ABTS_ASSERT(tc, "child terminated normally", why == APR_PROC_EXIT); +#endif } abts_suite *testpipe(abts_suite *suite) diff -urN apr-1.0.1.orig/test/testpoll.c apr-1.0.1/test/testpoll.c --- apr-1.0.1.orig/test/testpoll.c 2004-07-06 05:38:06.000000000 +0200 +++ apr-1.0.1/test/testpoll.c 2004-12-17 15:19:11.000000000 +0100 @@ -21,6 +21,11 @@ #include "apr_network_io.h" #include "apr_poll.h" +/* non-BONE BeOS select() only supports the read set */ +#if defined(BEOS) && !defined(HAVE_BONE_VERSION) +# define NO_POLLOUT_SUPPORT 1 +#endif + #define SMALL_NUM_SOCKETS 3 /* We can't use 64 here, because some platforms *ahem* Solaris *ahem* have * a default limit of 64 open file descriptors per process. If we use @@ -425,6 +430,9 @@ static void pollset_remove(abts_case *tc, void *data) { +#ifdef NO_POLLOUT_SUPPORT + ABTS_NOT_IMPL(tc, "no APR_POLLOUT support"); +#else apr_status_t rv; apr_pollset_t *pollset; const apr_pollfd_t *hot_files; @@ -497,6 +505,7 @@ (hot_files[1].client_data == (void *)4)) || ((hot_files[0].client_data == (void *)4) && (hot_files[1].client_data == (void *)1))); +#endif } abts_suite *testpoll(abts_suite *suite) @@ -527,9 +536,7 @@ abts_run_test(suite, clear_middle_pollset, NULL); abts_run_test(suite, send_last_pollset, NULL); abts_run_test(suite, clear_last_pollset, NULL); - abts_run_test(suite, pollset_remove, NULL); - abts_run_test(suite, close_all_sockets, NULL); return suite; diff -urN apr-1.0.1.orig/test/testsockopt.c apr-1.0.1/test/testsockopt.c --- apr-1.0.1.orig/test/testsockopt.c 2004-08-01 00:36:03.000000000 +0200 +++ apr-1.0.1/test/testsockopt.c 2004-12-17 15:19:11.000000000 +0100 @@ -19,6 +19,11 @@ #include "apr_lib.h" #include "testutil.h" +/* non-BONE BeOS versions don't know SO_KEEPALIVE */ +#if defined(BEOS) && !defined(HAVE_BONE_VERSION) +# define NO_SO_KEEPALIVE 1 +#endif + static apr_socket_t *sock = NULL; static void create_socket(abts_case *tc, void *data) @@ -32,6 +37,9 @@ static void set_keepalive(abts_case *tc, void *data) { +#ifdef NO_SO_KEEPALIVE + ABTS_NOT_IMPL(tc, "no SO_KEEPALIVE socket option"); +#else apr_status_t rv; apr_int32_t ck; @@ -41,6 +49,7 @@ rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_INT_EQUAL(tc, 1, ck); +#endif } static void set_debug(abts_case *tc, void *data) @@ -62,6 +71,9 @@ static void remove_keepalive(abts_case *tc, void *data) { +#ifdef NO_SO_KEEPALIVE + ABTS_NOT_IMPL(tc, "no SO_KEEPALIVE socket option"); +#else apr_status_t rv; apr_int32_t ck; @@ -75,6 +87,7 @@ rv = apr_socket_opt_get(sock, APR_SO_KEEPALIVE, &ck); ABTS_INT_EQUAL(tc, APR_SUCCESS, rv); ABTS_INT_EQUAL(tc, 0, ck); +#endif } static void corkable(abts_case *tc, void *data) diff -urN apr-1.0.1.orig/threadproc/beos/Makefile.in apr-1.0.1/threadproc/beos/Makefile.in --- apr-1.0.1.orig/threadproc/beos/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ apr-1.0.1/threadproc/beos/Makefile.in 2004-12-17 15:18:45.000000000 +0100 @@ -0,0 +1,21 @@ +srcdir = @srcdir@ +VPATH = @srcdir@ + +TARGETS = \ + apr_proc_stub + +# bring in rules.mk for standard functionality +@INCLUDE_RULES@ + +INCDIR=../../include +OSDIR=$(INCDIR)/arch/@OSDIR@ +DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@ +INCLUDES=-I$(INCDIR) -I$(INCDIR)/arch -I$(OSDIR) -I$(DEFOSDIR) + +CLEAN_TARGETS = apr_proc_stub /boot/home/config/bin/apr_proc_stub + +apr_proc_stub: + $(CC) apr_proc_stub.c \ + && cp apr_proc_stub /boot/home/config/bin + +# DO NOT REMOVE diff -urN apr-1.0.1.orig/threadproc/beos/apr_proc_stub.c apr-1.0.1/threadproc/beos/apr_proc_stub.c --- apr-1.0.1.orig/threadproc/beos/apr_proc_stub.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/threadproc/beos/apr_proc_stub.c 2004-12-17 15:19:11.000000000 +0100 @@ -13,15 +13,17 @@ * limitations under the License. */ +#include #include #include #include #include struct pipefd { - int in; - int out; - int err; + int in; + int out; + int err; + port_id port; }; int main(int argc, char *argv[]) { @@ -32,44 +34,65 @@ * argv[2] = progname to execute * rest of arguments to be passed to program */ - char *progname = argv[2]; - char *directory = argv[1]; - struct pipefd *pfd; - thread_id sender; - void *buffer; - char ** newargs; - int i = 0; - - newargs = (char**)malloc(sizeof(char*) * (argc - 1)); - - buffer = (void*)malloc(sizeof(struct pipefd)); - /* this will block until we get the data */ - receive_data(&sender, buffer, sizeof(struct pipefd)); - pfd = (struct pipefd*)buffer; - - if (pfd->in > STDERR_FILENO) { - if (dup2(pfd->in, STDIN_FILENO) != STDIN_FILENO) return (-1); - close (pfd->in); - } - if (pfd->out > STDERR_FILENO) { - if (dup2(pfd->out, STDOUT_FILENO) != STDOUT_FILENO) return (-1); - close (pfd->out); - } - if (pfd->err > STDERR_FILENO) { - if (dup2(pfd->err, STDERR_FILENO) != STDERR_FILENO) return (-1); - close (pfd->err); - } - - for (i=3;i<=argc;i++){ - newargs[i-3] = argv[i]; - } - - /* tell the caller we're OK to start */ - send_data(sender,1,NULL,0); - - if (directory != NULL) - chdir(directory); - execve (progname, newargs, environ); + char *progname = argv[2]; + char *directory = argv[1]; + struct pipefd pfd; + thread_id sender; + char **newargs = argv + 3; + int i = 0; + status_t error = B_OK; + + /* this will block until we get the data */ + receive_data(&sender, &pfd, sizeof(struct pipefd)); + + if (argc < 3) + error = B_BAD_VALUE; + + newargs = (char**)malloc(sizeof(char*) * (argc - 1)); + for (i=3;i<=argc;i++) { + newargs[i-3] = argv[i]; + } + + if (error == B_OK && pfd.in > STDERR_FILENO) { + if (dup2(pfd.in, STDIN_FILENO) != STDIN_FILENO) + error = errno; + close(pfd.in); + } + if (error == B_OK && pfd.out > STDERR_FILENO) { + if (dup2(pfd.out, STDOUT_FILENO) != STDOUT_FILENO) + error = errno; + close(pfd.out); + } + if (error == B_OK && pfd.err > STDERR_FILENO) { + if (dup2(pfd.err, STDERR_FILENO) != STDERR_FILENO) + error = errno; + close(pfd.err); + } + + if (error == B_OK && chdir(directory) < 0) + error = errno; + + if (error == B_OK) { + /* get our parent's team ID (the port owner) and our team ID */ + port_info portInfo; + thread_info threadInfo; + get_port_info(pfd.port, &portInfo); + get_thread_info(find_thread(NULL), &threadInfo); + + /* transfer the port ownership to us, so the the port will + * automatically be deleted, if execv() succeeds */ + set_port_owner(pfd.port, threadInfo.team); + + if (execv(progname, newargs) < 0) + error = errno; + + /* execv() failed; transfer the port ownership back to our parent, + * so that we can send the error code to it */ + set_port_owner(pfd.port, portInfo.team); + } - return (-1); + /* something went wrong; send our parent the error code */ + write_port(pfd.port, 0, &error, sizeof(error)); + + return (-1); } diff -urN apr-1.0.1.orig/threadproc/beos/proc.c apr-1.0.1/threadproc/beos/proc.c --- apr-1.0.1.orig/threadproc/beos/proc.c 2004-06-29 18:35:57.000000000 +0200 +++ apr-1.0.1/threadproc/beos/proc.c 2004-12-17 15:19:11.000000000 +0100 @@ -13,13 +13,22 @@ * limitations under the License. */ +#include "apr_arch_shm.h" #include "apr_arch_threadproc.h" +#include "apr_random.h" +#include "apr_signal.h" #include "apr_strings.h" +#include +#include + +#include + struct send_pipe { - int in; - int out; - int err; + int in; + int out; + int err; + port_id port; }; APR_DECLARE(apr_status_t) apr_procattr_create(apr_procattr_t **new, apr_pool_t *pool) @@ -113,18 +122,11 @@ APR_DECLARE(apr_status_t) apr_procattr_dir_set(apr_procattr_t *attr, const char *dir) { - char * cwd; - if (dir[0] != '/') { - cwd = (char*)malloc(sizeof(char) * PATH_MAX); - getcwd(cwd, PATH_MAX); - attr->currdir = (char *)apr_pstrcat(attr->pool, cwd, "/", dir, NULL); - free(cwd); - } else { - attr->currdir = (char *)apr_pstrdup(attr->pool, dir); - } + attr->currdir = apr_pstrdup(attr->pool, dir); if (attr->currdir) { return APR_SUCCESS; } + return APR_ENOMEM; } @@ -144,53 +146,53 @@ APR_DECLARE(apr_status_t) apr_proc_fork(apr_proc_t *proc, apr_pool_t *pool) { int pid; + port_id port; + status_t error = B_OK; + status_t childInitError = B_OK; + int32 code; + + /* we create a port through which the child will send us whether its + * initialization was successful */ + port = create_port(1, "apr_fork"); + if (port < 0) + return port; if ((pid = fork()) < 0) { + delete_port(port); return errno; } else if (pid == 0) { - /* This is really ugly... - * The semantics of BeOS's fork() are that areas (used for shared - * memory) get COW'd :-( The only way we can make shared memory - * work across fork() is therefore to find any areas that have - * been created and then clone them into our address space. - * Thankfully only COW'd areas have the lock variable set at - * anything but 0, so we can use that to find the areas we need to - * copy. Of course what makes it even worse is that the loop through - * the area's will go into an infinite loop, eating memory and then - * eventually segfault unless we know when we reach then end of the - * "original" areas and stop. Why? Well, we delete the area and then - * add another to the end of the list... - */ - area_info ai; - int32 cookie = 0; - area_id highest = 0; - - while (get_next_area_info(0, &cookie, &ai) == B_OK) - if (ai.area > highest) - highest = ai.area; - cookie = 0; - while (get_next_area_info(0, &cookie, &ai) == B_OK) { - if (ai.area > highest) - break; - if (ai.lock > 0) { - area_id original = find_area(ai.name); - delete_area(ai.area); - clone_area(ai.name, &ai.address, B_CLONE_ADDRESS, - ai.protection, original); - } - } - proc->pid = pid; - proc->in = NULL; + proc->in = NULL; proc->out = NULL; proc->err = NULL; + + error = apr_beos_shmem_child_init(); + write_port(port, 0, &error, sizeof(error)); + if (error != B_OK) + exit(1); + + apr_random_after_fork(proc); + return APR_INCHILD; } proc->pid = pid; proc->in = NULL; proc->out = NULL; proc->err = NULL; + + /* get the child initialization status */ + do { + error = read_port(port, &code, &childInitError, sizeof(childInitError)); + } while (error == EINTR); + + delete_port(port); + + if (error >= B_OK) + error = childInitError; + if (error != B_OK) + return error; + return APR_INPARENT; } @@ -215,62 +217,234 @@ return APR_SUCCESS; } +static status_t find_program(const char **resolvedProgramName, + const char *programName, apr_procattr_t *attr, + const char *const *env, apr_pool_t *pool) +{ + const char *pathVarName = "PATH="; + int pathVarNameLen = strlen(pathVarName); + const char *paths = NULL; + int programNameLen = strlen(programName); + int i; + + /* If the program name is absolute, then there's nothing to do. + * If the program name consists of more than one path element, then we + * consider it a relative path and don't search in PATH either. */ + if (*programName == '/' || strchr(programName, '/')) { + *resolvedProgramName = programName; + return B_OK; + } + + /* get the PATH environment variable */ + for (i = 0; env[i]; i++) { + const char *var = env[i]; + if (strncmp(var, pathVarName, pathVarNameLen) == 0) { + paths = var + pathVarNameLen; + break; + } + } + if (!paths) + return APR_ENOENT; + + /* iterate through the paths */ + do { + const char *pathEnd = strchr(paths, ':'); + int pathLen = (pathEnd ? pathEnd - paths : strlen(paths)); + + /* We skip empty paths and those that would become too long. + * The latter is not really correct, but practically irrelevant. */ + if (pathLen > 0 + && pathLen + 1 + programNameLen < B_PATH_NAME_LENGTH) { + /* get the path */ + char path[B_PATH_NAME_LENGTH]; + struct stat st; + memcpy(path, paths, pathLen); + path[pathLen] = '\0'; + + /* get the program path */ + strcat(path, "/"); + strcat(path, programName); + + /* stat() the path to be sure, there is a file */ + if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) { + /* If the path is relative, we make it absolute by + * prepending the current working directory, so there + * won't be problems when changing the cwd later */ + if (*path == '/') { + *resolvedProgramName = apr_pstrdup(pool, path); + } + else { + char cwd[B_PATH_NAME_LENGTH]; + getcwd(cwd, sizeof(cwd)); + *resolvedProgramName = apr_pstrcat(pool, cwd, "/", + path, NULL); + } + return B_OK; + } + } + + paths = (pathEnd ? pathEnd + 1 : NULL); + } while (paths); + + /* not found in PATH */ + return APR_ENOENT; +} + +typedef struct char_buffer { + char *buffer; + int size; +} char_buffer; + +static void append_char(char_buffer *buffer, char c) +{ + if (buffer->buffer) { + *(buffer->buffer) = c; + buffer->buffer++; + } + buffer->size++; +} + +static void prepare_shell_args(const char *progname, const char * const *args, + int argc, char_buffer *buffer) +{ + int i; + + for (i = 0; i < argc; i++) { + const char *arg = args[i]; + + /* replace the first argument with the program name and separate the + * other arguments with a space */ + if (i == 0) + arg = progname; + else + append_char(buffer, ' '); + + if (*arg == '\0') { + /* empty arg */ + append_char(buffer, '"'); + append_char(buffer, '"'); + } + else { + while (*arg) { + /* escape special characters */ + if (strchr(" ()?*&\"'[]^\\~|;!<>*$", *arg)) + append_char(buffer, '\\'); + append_char(buffer, *arg); + arg++; + } + } + } +} + APR_DECLARE(apr_status_t) apr_proc_create(apr_proc_t *new, const char *progname, const char * const *args, const char * const *env, apr_procattr_t *attr, apr_pool_t *pool) { - int i=0,nargs=0; - char **newargs = NULL; - thread_id newproc, sender; - struct send_pipe *sp; - char * dir = NULL; - - sp = (struct send_pipe *)apr_palloc(pool, sizeof(struct send_pipe)); + int i = 0, nargs = 0; + const char **newargs = NULL; + thread_id newproc; + struct send_pipe sp; + const char *shellArgs[4] = { SHELL_PATH, "-c", NULL, NULL }; + status_t error; + status_t childError; new->in = attr->parent_in; new->err = attr->parent_err; new->out = attr->parent_out; - sp->in = attr->child_in ? attr->child_in->filedes : -1; - sp->out = attr->child_out ? attr->child_out->filedes : -1; - sp->err = attr->child_err ? attr->child_err->filedes : -1; + sp.in = attr->child_in ? attr->child_in->filedes : -1; + sp.out = attr->child_out ? attr->child_out->filedes : -1; + sp.err = attr->child_err ? attr->child_err->filedes : -1; + + /* Get the correct environment to use. */ + switch (attr->cmdtype) { + case APR_SHELLCMD: + case APR_PROGRAM: + break; + case APR_PROGRAM_ENV: + case APR_PROGRAM_PATH: + case APR_SHELLCMD_ENV: + env = (const char *const*)environ; + break; + } + if (!env) + env = (const char *const*)environ; + + /* In case of APR_PROGRAM_PATH we need to find the program ourselves. In + * the other cases, the program name shall either be considered a path or + * the shell searches for the program. */ + if (attr->cmdtype == APR_PROGRAM_PATH) { + error = find_program(&progname, progname, attr, env, pool); + if (error != B_OK) + return error; + } + + /* if the program shall be started via shell, we need to prepare the + * arguments */ + if (attr->cmdtype == APR_SHELLCMD || attr->cmdtype == APR_SHELLCMD_ENV) { + char_buffer charBuffer = { NULL, 0 }; + int argc = 0; + + /* count the arguments */ + while (args && args[argc]) { + argc++; + } + if (argc == 0) + return APR_EINVAL; + + /* first we get the length */ + prepare_shell_args(progname, args, argc, &charBuffer); + /* allocate the memory and get the args for real */ + charBuffer.buffer = (char*)apr_palloc(pool, charBuffer.size + 1); + charBuffer.size = 0; + shellArgs[2] = charBuffer.buffer; + prepare_shell_args(progname, args, argc, &charBuffer); + *(charBuffer.buffer) = '\0'; + + /* replace the program name and the arguments */ + progname = shellArgs[0]; + args = shellArgs; + } + + /* count the arguments */ i = 0; while (args && args[i]) { i++; } - newargs = (char**)malloc(sizeof(char *) * (i + 4)); - newargs[0] = strdup("/boot/home/config/bin/apr_proc_stub"); + newargs = (const char**)malloc(sizeof(const char *) * (i + 4)); + newargs[0] = "/boot/home/config/bin/apr_proc_stub"; if (attr->currdir == NULL) { - /* we require the directory , so use a temp. variable */ - dir = malloc(sizeof(char) * PATH_MAX); - getcwd(dir, PATH_MAX); - newargs[1] = strdup(dir); - free(dir); - } else { - newargs[1] = strdup(attr->currdir); + newargs[1] = "."; } - newargs[2] = strdup(progname); + else { + newargs[1] = attr->currdir; + } + newargs[2] = progname; i=0;nargs = 3; while (args && args[i]) { - newargs[nargs] = strdup(args[i]); + newargs[nargs] = args[i]; i++;nargs++; } newargs[nargs] = NULL; - /* ### we should be looking at attr->cmdtype in here... */ - - newproc = load_image(nargs, (const char**)newargs, (const char**)env); + /* create a temporary port, the stub will use to report an error back to + * us */ + sp.port = create_port(1, "apr_proc_create"); + if (sp.port < 0) + return sp.port; + + /* load the stub */ + newproc = load_image(nargs, newargs, (const char**)env); /* load_image copies the data so now we can free it... */ - while (--nargs >= 0) - free (newargs[nargs]); free(newargs); if (newproc < B_NO_ERROR) { + delete_port(sp.port); return errno; } @@ -286,15 +460,25 @@ apr_file_close(attr->child_err); } - send_data(newproc, 0, (void*)sp, sizeof(struct send_pipe)); + send_data(newproc, 0, &sp, sizeof(struct send_pipe)); new->pid = newproc; /* before we go charging on we need the new process to get to a - * certain point. When it gets there it'll let us know and we - * can carry on. */ - receive_data(&sender, (void*)NULL,0); - - return APR_SUCCESS; + * certain point. The stub will either send us an error code back through + * the port or simply delete the port, when everything went fine. */ + do { + int32 code; + error = read_port(sp.port, &code, &childError, sizeof(childError)); + } while (error == EINTR); + + if (error == B_BAD_PORT_ID) + return APR_SUCCESS; + + delete_port(sp.port); + + if (error >= B_OK) + return childError; + return error; } APR_DECLARE(apr_status_t) apr_proc_wait_all_procs(apr_proc_t *proc, @@ -360,10 +544,10 @@ apr_file_pipe_create(&attr->child_in, &attr->parent_in, attr->pool); if (child_in != NULL) - apr_file_dup(&attr->child_in, child_in, attr->pool); + apr_file_dup2(attr->child_in, child_in, attr->pool); if (parent_in != NULL) - apr_file_dup(&attr->parent_in, parent_in, attr->pool); + apr_file_dup2(attr->parent_in, parent_in, attr->pool); return APR_SUCCESS; } @@ -375,10 +559,10 @@ apr_file_pipe_create(&attr->child_out, &attr->parent_out, attr->pool); if (child_out != NULL) - apr_file_dup(&attr->child_out, child_out, attr->pool); + apr_file_dup2(attr->child_out, child_out, attr->pool); if (parent_out != NULL) - apr_file_dup(&attr->parent_out, parent_out, attr->pool); + apr_file_dup2(attr->parent_out, parent_out, attr->pool); return APR_SUCCESS; } @@ -390,10 +574,10 @@ apr_file_pipe_create(&attr->child_err, &attr->parent_err, attr->pool); if (child_err != NULL) - apr_file_dup(&attr->child_err, child_err, attr->pool); + apr_file_dup2(attr->child_err, child_err, attr->pool); if (parent_err != NULL) - apr_file_dup(&attr->parent_err, parent_err, attr->pool); + apr_file_dup2(attr->parent_err, parent_err, attr->pool); return APR_SUCCESS; } diff -urN apr-1.0.1.orig/threadproc/beos/thread.c apr-1.0.1/threadproc/beos/thread.c --- apr-1.0.1.orig/threadproc/beos/thread.c 2004-06-10 12:57:25.000000000 +0200 +++ apr-1.0.1/threadproc/beos/thread.c 2004-12-17 15:19:11.000000000 +0100 @@ -26,27 +26,27 @@ } (*new)->pool = pool; - (*new)->attr = (int32)B_NORMAL_PRIORITY; + (*new)->attr = (int32)B_NORMAL_PRIORITY; return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_threadattr_detach_set(apr_threadattr_t *attr, apr_int32_t on) { - if (on == 1){ - attr->detached = 1; - } else { - attr->detached = 0; - } + if (on == 1){ + attr->detached = 1; + } else { + attr->detached = 0; + } return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_threadattr_detach_get(apr_threadattr_t *attr) { - if (attr->detached == 1){ - return APR_DETACH; - } - return APR_NOTDETACH; + if (attr->detached == 1){ + return APR_DETACH; + } + return APR_NOTDETACH; } APR_DECLARE(apr_status_t) apr_threadattr_stacksize_set(apr_threadattr_t *attr, @@ -61,10 +61,11 @@ return APR_ENOTIMPL; } -static void *dummy_worker(void *opaque) +static int32 dummy_worker(void *opaque) { apr_thread_t *thd = (apr_thread_t*)opaque; - return thd->func(thd, thd->data); + thd->func(thd, thd->data); + return 0; } APR_DECLARE(apr_status_t) apr_thread_create(apr_thread_t **new, apr_threadattr_t *attr, @@ -82,23 +83,21 @@ (*new)->pool = pool; (*new)->data = data; (*new)->func = func; - (*new)->exitval = -1; + (*new)->exitval = 0; + (*new)->join_count = 0; /* First we create the new thread...*/ - if (attr) - temp = attr->attr; - else - temp = B_NORMAL_PRIORITY; + if (attr) + temp = attr->attr; + else + temp = B_NORMAL_PRIORITY; stat = apr_pool_create(&(*new)->pool, pool); if (stat != APR_SUCCESS) { return stat; } - (*new)->td = spawn_thread((thread_func)dummy_worker, - "apr thread", - temp, - (*new)); + (*new)->td = spawn_thread(dummy_worker, "apr thread", temp, (*new)); /* Now we try to run it...*/ if (resume_thread((*new)->td) == B_NO_ERROR) { @@ -128,7 +127,8 @@ return APR_SUCCESS; } -APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, apr_thread_t *thd) +APR_DECLARE(apr_status_t) apr_thread_join(apr_status_t *retval, + apr_thread_t *thd) { status_t rv = 0, ret; ret = wait_for_thread(thd->td, &rv); @@ -137,10 +137,10 @@ return APR_SUCCESS; } else { - /* if we've missed the thread's death, did we set an exit value prior - * to it's demise? If we did return that. + /* We've missed the thread's death, if noone joined it before us, we + * will succeed. */ - if (thd->exitval != -1) { + if (atomic_add(&thd->join_count, 1) == 0) { *retval = thd->exitval; return APR_SUCCESS; } else @@ -150,12 +150,27 @@ APR_DECLARE(apr_status_t) apr_thread_detach(apr_thread_t *thd) { - if (suspend_thread(thd->td) == B_NO_ERROR){ + /* + if (suspend_thread(thd->td) == B_NO_ERROR){ return APR_SUCCESS; } else { return errno; } + + * bonefish: + * The code above is definitely not correct. The OpenGroup specification + * of pthread_detach() says: + * + * "The pthread_detach() function shall indicate to the implementation that + * storage for the thread thread can be reclaimed when that thread + * terminates. If thread has not terminated, pthread_detach() shall not + * cause it to terminate. The effect of multiple pthread_detach() calls + * on the same target thread is unspecified." + * + * I don't really see, what we should do here. + */ + return APR_SUCCESS; } void apr_thread_yield() @@ -198,10 +213,8 @@ { apr_thread_once_t *control = (apr_thread_once_t *)vcontrol; - if (control->sem) { - release_sem(control->sem); + if (control->sem >= 0) delete_sem(control->sem); - } return APR_SUCCESS; } @@ -211,7 +224,6 @@ { int rc; *control = (apr_thread_once_t *)apr_pcalloc(p, sizeof(apr_thread_once_t)); - (*control)->hit = 0; /* we haven't done it yet... */ rc = ((*control)->sem = create_sem(1, "thread_once")); if (rc < 0) return rc; @@ -225,10 +237,11 @@ APR_DECLARE(apr_status_t) apr_thread_once(apr_thread_once_t *control, void (*func)(void)) { - if (!control->hit) { + if (control->sem >= 0) { if (acquire_sem(control->sem) == B_OK) { - control->hit = 1; func(); + delete_sem(control->sem); + control->sem = -1; } } return APR_SUCCESS; diff -urN apr-1.0.1.orig/threadproc/beos/threadpriv.c apr-1.0.1/threadproc/beos/threadpriv.c --- apr-1.0.1.orig/threadproc/beos/threadpriv.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/threadproc/beos/threadpriv.c 2004-12-17 15:19:11.000000000 +0100 @@ -14,135 +14,51 @@ */ #include "apr_arch_threadproc.h" +#include -static struct beos_key key_table[BEOS_MAX_DATAKEYS]; -static struct beos_private_data *beos_data[BEOS_MAX_DATAKEYS]; -static sem_id lock; +static void threadkey_cleanup(void *_key) +{ + apr_threadkey_t *key = (apr_threadkey_t *)_key; + void* data = tls_get(key->key); + + if (data && key->destructor) { + (*key->destructor)(data); + } +} APR_DECLARE(apr_status_t) apr_threadkey_private_create(apr_threadkey_t **key, void (*dest)(void *), apr_pool_t *pool) { - (*key) = (apr_threadkey_t *)apr_palloc(pool, sizeof(apr_threadkey_t)); + (*key) = (apr_threadkey_t *)apr_pcalloc(pool, sizeof(apr_threadkey_t)); + if ((*key) == NULL) { return APR_ENOMEM; } + (*key)->key = tls_allocate(); (*key)->pool = pool; - - acquire_sem(lock); - for ((*key)->key=0; (*key)->key < BEOS_MAX_DATAKEYS; (*key)->key++){ - if (key_table[(*key)->key].assigned == 0){ - key_table[(*key)->key].assigned = 1; - key_table[(*key)->key].destructor = dest; - release_sem(lock); - return APR_SUCCESS; - } - - } - release_sem(lock); - return APR_ENOMEM; + (*key)->destructor = dest; + + on_exit_thread(&threadkey_cleanup, *key); + + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_threadkey_private_get(void **new, apr_threadkey_t *key) { - thread_id tid; - int i, index=0; - tid = find_thread(NULL); - for (i=0;idata){ - /* it's been used */ - if (beos_data[i]->td == tid){ - index = i; - } - } - } - if (index == 0){ - /* no storage for thread so we can't get anything... */ - return APR_ENOMEM; - } - - if ((key->key < BEOS_MAX_DATAKEYS) && (key_table)){ - acquire_sem(key_table[key->key].lock); - if (key_table[key->key].count){ - (*new) = (void*)beos_data[index]->data[key->key]; - } else { - (*new) = NULL; - } - release_sem(key_table[key->key].lock); - } else { - (*new) = NULL; - } - return APR_SUCCESS; + (*new) = tls_get(key->key); + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_threadkey_private_set(void *priv, apr_threadkey_t *key) { - thread_id tid; - int i,index = 0, ret = 0; - - tid = find_thread(NULL); - for (i=0; i < BEOS_MAX_DATAKEYS; i++){ - if (beos_data[i]->data){ - if (beos_data[i]->td == tid){index = i;} - } - } - if (index==0){ - /* not yet been allocated */ - for (i=0; i< BEOS_MAX_DATAKEYS; i++){ - if (! beos_data[i]->data){ - /* we'll take this one... */ - index = i; - beos_data[i]->data = (const void **)malloc(sizeof(void *) * BEOS_MAX_DATAKEYS); - memset((void *)beos_data[i]->data, 0, sizeof(void *) * BEOS_MAX_DATAKEYS); - beos_data[i]->count = (int)malloc(sizeof(int)); - beos_data[i]->td = (thread_id)malloc(sizeof(thread_id)); - beos_data[i]->td = tid; - } - } - } - if (index == 0){ - /* we're out of luck.. */ - return APR_ENOMEM; - } - if ((key->key < BEOS_MAX_DATAKEYS) && (key_table)){ - acquire_sem(key_table[key->key].lock); - if (key_table[key->key].count){ - if (beos_data[index]->data[key->key] == NULL){ - if (priv != NULL){ - beos_data[index]->count++; - key_table[key->key].count++; - } - } else { - if (priv == NULL){ - beos_data[index]->count--; - key_table[key->key].count--; - } - } - beos_data[index]->data[key->key] = priv; - ret = 1; - } else { - ret = 0; - } - release_sem(key_table[key->key].lock); - } - if (ret) - return APR_SUCCESS; - return APR_ENOMEM; + tls_set(key->key, priv); + return APR_SUCCESS; } APR_DECLARE(apr_status_t) apr_threadkey_private_delete(apr_threadkey_t *key) { - if (key->key < BEOS_MAX_DATAKEYS){ - acquire_sem(key_table[key->key].lock); - if (key_table[key->key].count == 1){ - key_table[key->key].destructor = NULL; - key_table[key->key].count = 0; - } - release_sem(key_table[key->key].lock); - } else { - return APR_ENOMEM; - } - return APR_SUCCESS; + return APR_ENOTIMPL; } APR_DECLARE(apr_status_t) apr_threadkey_data_get(void **data, const char *key, diff -urN apr-1.0.1.orig/user/unix/userinfo.c apr-1.0.1/user/unix/userinfo.c --- apr-1.0.1.orig/user/unix/userinfo.c 2004-02-13 10:38:38.000000000 +0100 +++ apr-1.0.1/user/unix/userinfo.c 2004-12-17 15:19:11.000000000 +0100 @@ -31,6 +31,28 @@ #define PWBUF_SIZE 512 +/* on BeOS R5 (also for BONE systems?) getpwnam() is broken */ +#ifdef BEOS +static struct passwd *beos_getpwnam(const char *name) +{ + struct passwd *p; + while ((p = getpwent()) != NULL) { + if (strcmp(p->pw_name, name) == 0) + break; + } + endpwent(); + + if (!p) { + errno = ENOENT; + /* probably not the correct error code, but that doesn't really + * matter anyway */ + } + return p; +} +#define getpwnam beos_getpwnam +#endif + + static apr_status_t getpwnam_safe(const char *username, struct passwd *pw, char pwbuf[PWBUF_SIZE])