⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apr_pools.c

📁 Apache V2.0.15 Alpha For Linuxhttpd-2_0_15-alpha.tar.Z
💻 C
📖 第 1 页 / 共 3 页
字号:
	b = b->parent;    }    return 0;}/* * All blocks belonging to sub will be changed to point to p * instead.  This is a guarantee by the caller that sub will not * be destroyed before p is. */APR_DECLARE(void) apr_pool_join(apr_pool_t *p, apr_pool_t *sub){    union block_hdr *b;    /* We could handle more general cases... but this is it for now. */    if (sub->parent != p) {	fprintf(stderr, "pool_join: p is not parent of sub\n");	abort();    }    while (p->joined) {	p = p->joined;    }    sub->joined = p;    for (b = global_block_list; b; b = b->h.global_next) {	if (b->h.owning_pool == sub) {	    b->h.owning_pool = p;	}    }    return 0;}#endif/***************************************************************** * * Allocating stuff... */APR_DECLARE(void*) apr_palloc(apr_pool_t *a, apr_size_t reqsize){#ifdef ALLOC_USE_MALLOC    apr_size_t size = reqsize + CLICK_SZ;    void *ptr;    ptr = malloc(size);    if (ptr == NULL) {	fputs("Ouch!  Out of memory!\n", stderr);	exit(1);    }    debug_fill(ptr, size); /* might as well get uninitialized protection */    *(void **)ptr = a->allocation_list;    a->allocation_list = ptr;    return (char *)ptr + CLICK_SZ;#else    /*     * Round up requested size to an even number of alignment units     * (core clicks)     */    apr_size_t nclicks;    apr_size_t size;    /* First, see if we have space in the block most recently     * allocated to this pool     */    union block_hdr *blok;    char *first_avail;    char *new_first_avail;    nclicks = 1 + ((reqsize - 1) / CLICK_SZ);    size = nclicks * CLICK_SZ;    /* First, see if we have space in the block most recently     * allocated to this pool     */    blok = a->last;    first_avail = blok->h.first_avail;    if (reqsize <= 0) {	return NULL;    }    new_first_avail = first_avail + size;    if (new_first_avail <= blok->h.endp) {	debug_verify_filled(first_avail, blok->h.endp,			    "[apr_palloc] Ouch!  Someone trounced past the end "			    "of their allocation!\n");	blok->h.first_avail = new_first_avail;	return (void *) first_avail;    }    /* Nope --- get a new one that's guaranteed to be big enough */#if APR_HAS_THREADS    if (alloc_mutex) {        apr_lock_acquire(alloc_mutex);    }#endif    blok = new_block(size, a->apr_abort);    a->last->h.next = blok;    a->last = blok;#ifdef APR_POOL_DEBUG    blok->h.owning_pool = a;#endif#if APR_HAS_THREADS    if (alloc_mutex) {        apr_lock_release(alloc_mutex);    }#endif    first_avail = blok->h.first_avail;    blok->h.first_avail += size;    return (void *) first_avail;#endif}APR_DECLARE(void *) apr_pcalloc(apr_pool_t *a, apr_size_t size){    void *res = apr_palloc(a, size);    memset(res, '\0', size);    return res;}/***************************************************************** * * User data management functions */APR_DECLARE(apr_status_t) apr_pool_userdata_set(const void *data, const char *key,			      apr_status_t (*cleanup) (void *),			      apr_pool_t *cont){    int keylen = strlen(key);    if (cont->prog_data == NULL)        cont->prog_data = apr_hash_make(cont);    if (apr_hash_get(cont->prog_data, key, keylen) == NULL){        char *new_key = apr_pstrdup(cont, key);        apr_hash_set(cont->prog_data, new_key, keylen, data);    }     else {        apr_hash_set(cont->prog_data, key, keylen, data);    }    apr_pool_cleanup_register(cont, data, cleanup, cleanup);    return APR_SUCCESS;}APR_DECLARE(apr_status_t) apr_pool_userdata_get(void **data, const char *key, apr_pool_t *cont){    if (cont->prog_data == NULL)        *data = NULL;    else        *data = apr_hash_get(cont->prog_data, key, strlen(key));    return APR_SUCCESS;}/***************************************************************** * * "Print" functions *//* * apr_psprintf is implemented by writing directly into the current * block of the pool, starting right at first_avail.  If there's * insufficient room, then a new block is allocated and the earlier * output is copied over.  The new block isn't linked into the pool * until all the output is done. * * Note that this is completely safe because nothing else can * allocate in this apr_pool_t while apr_psprintf is running.  alarms are * blocked, and the only thing outside of alloc.c that's invoked * is apr_vformatter -- which was purposefully written to be * self-contained with no callouts. */struct psprintf_data {    apr_vformatter_buff_t vbuff;#ifdef ALLOC_USE_MALLOC    char *base;#else    union block_hdr *blok;    int got_a_new_block;#endif};static int psprintf_flush(apr_vformatter_buff_t *vbuff){    struct psprintf_data *ps = (struct psprintf_data *)vbuff;#ifdef ALLOC_USE_MALLOC    apr_size_t size;    char *ptr;    size = (char *)ps->vbuff.curpos - ps->base;    ptr = realloc(ps->base, 2*size);    if (ptr == NULL) {	fputs("Ouch!  Out of memory!\n", stderr);	exit(1);    }    ps->base = ptr;    ps->vbuff.curpos = ptr + size;    ps->vbuff.endpos = ptr + 2*size - 1;    return 0;#else    union block_hdr *blok;    union block_hdr *nblok;    apr_size_t cur_len;    char *strp;    blok = ps->blok;    strp = ps->vbuff.curpos;    cur_len = strp - blok->h.first_avail;    /* must try another blok */#if APR_HAS_THREADS    apr_lock_acquire(alloc_mutex);#endif    nblok = new_block(2 * cur_len, NULL);#if APR_HAS_THREADS    apr_lock_release(alloc_mutex);#endif    memcpy(nblok->h.first_avail, blok->h.first_avail, cur_len);    ps->vbuff.curpos = nblok->h.first_avail + cur_len;    /* save a byte for the NUL terminator */    ps->vbuff.endpos = nblok->h.endp - 1;    /* did we allocate the current blok? if so free it up */    if (ps->got_a_new_block) {	debug_fill(blok->h.first_avail, blok->h.endp - blok->h.first_avail);#if APR_HAS_THREADS        apr_lock_acquire(alloc_mutex);#endif	blok->h.next = block_freelist;	block_freelist = blok;#if APR_HAS_THREADS        apr_lock_release(alloc_mutex);#endif    }    ps->blok = nblok;    ps->got_a_new_block = 1;    /* note that we've deliberately not linked the new block onto     * the pool yet... because we may need to flush again later, and     * we'd have to spend more effort trying to unlink the block.     */    return 0;#endif}APR_DECLARE(char *) apr_pvsprintf(apr_pool_t *p, const char *fmt, va_list ap){#ifdef ALLOC_USE_MALLOC    struct psprintf_data ps;    void *ptr;    ps.base = malloc(512);    if (ps.base == NULL) {	fputs("Ouch!  Out of memory!\n", stderr);	exit(1);    }    /* need room at beginning for allocation_list */    ps.vbuff.curpos = ps.base + CLICK_SZ;    ps.vbuff.endpos = ps.base + 511;    apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);    *ps.vbuff.curpos++ = '\0';    ptr = ps.base;    /* shrink */    ptr = realloc(ptr, (char *)ps.vbuff.curpos - (char *)ptr);    if (ptr == NULL) {	fputs("Ouch!  Out of memory!\n", stderr);	exit(1);    }    *(void **)ptr = p->allocation_list;    p->allocation_list = ptr;    return (char *)ptr + CLICK_SZ;#else    struct psprintf_data ps;    char *strp;    apr_size_t size;    ps.blok = p->last;    ps.vbuff.curpos = ps.blok->h.first_avail;    ps.vbuff.endpos = ps.blok->h.endp - 1;	/* save one for NUL */    ps.got_a_new_block = 0;    apr_vformatter(psprintf_flush, &ps.vbuff, fmt, ap);    strp = ps.vbuff.curpos;    *strp++ = '\0';    size = strp - ps.blok->h.first_avail;    size = (1 + ((size - 1) / CLICK_SZ)) * CLICK_SZ;    strp = ps.blok->h.first_avail;	/* save away result pointer */    ps.blok->h.first_avail += size;    /* have to link the block in if it's a new one */    if (ps.got_a_new_block) {	p->last->h.next = ps.blok;	p->last = ps.blok;#ifdef APR_POOL_DEBUG	ps.blok->h.owning_pool = p;#endif    }    return strp;#endif}APR_DECLARE_NONSTD(char *) apr_psprintf(apr_pool_t *p, const char *fmt, ...){    va_list ap;    char *res;    va_start(ap, fmt);    res = apr_pvsprintf(p, fmt, ap);    va_end(ap);    return res;}/***************************************************************** * * More grotty system stuff... subprocesses.  Frump.  These don't use * the generic cleanup interface because I don't want multiple * subprocesses to result in multiple three-second pauses; the * subprocesses have to be "freed" all at once.  If someone comes * along with another resource they want to allocate which has the * same property, we might want to fold support for that into the * generic interface, but for now, it's a special case */APR_DECLARE(void) apr_pool_note_subprocess(apr_pool_t *a, apr_proc_t *pid,                                    enum kill_conditions how){    struct process_chain *new =    (struct process_chain *) apr_palloc(a, sizeof(struct process_chain));    new->pid = pid;    new->kill_how = how;    new->next = a->subprocesses;    a->subprocesses = new;}static void free_proc_chain(struct process_chain *procs){    /* Dispose of the subprocesses we've spawned off in the course of     * whatever it was we're cleaning up now.  This may involve killing     * some of them off...     */    struct process_chain *p;    int need_timeout = 0;    if (procs == NULL) {	return;			/* No work.  Whew! */    }    /* First, check to see if we need to do the SIGTERM, sleep, SIGKILL     * dance with any of the processes we're cleaning up.  If we've got     * any kill-on-sight subprocesses, ditch them now as well, so they     * don't waste any more cycles doing whatever it is that they shouldn't     * be doing anymore.     */#ifndef NEED_WAITPID    /* Pick up all defunct processes */    for (p = procs; p; p = p->next) {        if (apr_proc_wait(p->pid, APR_NOWAIT) == APR_CHILD_DONE) {            p->kill_how = kill_never;        }    }#endif    for (p = procs; p; p = p->next) {        if ((p->kill_how == kill_after_timeout)            || (p->kill_how == kill_only_once)) {            /*             * Subprocess may be dead already.  Only need the timeout if not.             * Note: apr_proc_kill on Windows is TerminateProcess(), which is              * similar to a SIGKILL, so always give the process a timeout             * under Windows before killing it.             */#ifdef WIN32            need_timeout = 1;#else	    if (apr_proc_kill(p->pid, SIGTERM) == APR_SUCCESS) {		need_timeout = 1;	    }#endif	}	else if (p->kill_how == kill_always) {	    apr_proc_kill(p->pid, SIGKILL);	}    }    /* Sleep only if we have to... */    if (need_timeout) {	sleep(3);    }    /* OK, the scripts we just timed out for have had a chance to clean up     * --- now, just get rid of them, and also clean up the system accounting     * goop...     */    for (p = procs; p; p = p->next) {	if (p->kill_how == kill_after_timeout) {	    apr_proc_kill(p->pid, SIGKILL);	}    }#ifdef WIN32    /*      * Do we need an APR function to clean-up a proc_t?     */    {        for (p = procs; p; p = p->next) {            CloseHandle((HANDLE)p->pid->pid);        }    }#endif /* WIN32 */    /* Now wait for all the signaled processes to die */    for (p = procs; p; p = p->next) {	if (p->kill_how != kill_never) {	    (void) apr_proc_wait(p->pid, APR_WAIT);	}    }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -