Commit a367240b authored by Brian Havard's avatar Brian Havard
Browse files

Catch exceptions in worker threads so a segfault doesn't kill all active

connections in the process. When this occurs, a graceful shutdown of the
child is initiated so any leaked resources & hosed memory is disposed of ASAP.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90400 13f79535-47bb-0310-9956-ffa450edef68
parent 9dfbe739
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -77,7 +77,6 @@
/*
 Todo list
 - Enforce MaxClients somehow
 - Catch thread exceptions & initiate graceful shutdown of child process
*/
#define CORE_PRIVATE
#define INCL_NOPMAPI
+37 −0
Original line number Diff line number Diff line
@@ -340,6 +340,39 @@ void add_worker()



ULONG APIENTRY thread_exception_handler(EXCEPTIONREPORTRECORD *pReportRec,
                                        EXCEPTIONREGISTRATIONRECORD *pRegRec,
                                        CONTEXTRECORD *pContext,
                                        PVOID p)
{
    int c;

    if (pReportRec->fHandlerFlags & EH_NESTED_CALL) {
        return XCPT_CONTINUE_SEARCH;
    }

    if (pReportRec->ExceptionNum == XCPT_ACCESS_VIOLATION ||
        pReportRec->ExceptionNum == XCPT_INTEGER_DIVIDE_BY_ZERO) {
        ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, ap_server_conf,
                     "caught exception in worker thread, initiating child shutdown pid=%d", getpid());
        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].tid == _gettid()) {
                ap_scoreboard_image->servers[child_slot][c].status = SERVER_DEAD;
                break;
            }
        }

        /* Shut down process ASAP, it could be quite unhealthy & leaking resources */
        shutdown_pending = 1;
        ap_scoreboard_image->parent[child_slot].quiescing = 1;
        DosUnwindException(UNWIND_ALL, 0, 0);
    }
  
    return XCPT_CONTINUE_SEARCH;
}



static void worker_main(void *vpArg)
{
    long conn_id;
@@ -353,6 +386,10 @@ static void worker_main(void *vpArg)
    ULONG len;
    BYTE priority;
    int thread_slot = (int)vpArg;
    EXCEPTIONREGISTRATIONRECORD reg_rec = { NULL, thread_exception_handler };
  
    /* Trap exceptions in this thread so we don't take down the whole process */
    DosSetExceptionHandler( &reg_rec );

    rc = DosOpenQueue(&owner, &workq,
                      apr_psprintf(pchild, "/queues/httpd/work.%d", getpid()));