/* Licensed to the Apache Software Foundation (ASF) under one or more *contributorlicenseagreements.SeetheNOTICEfiledistributedwith *thisworkforadditionalinformationregardingcopyrightownership. *TheASFlicensesthisfiletoYouundertheApacheLicense,Version2.0 *(the"License");youmaynotusethisfileexceptincompliancewith *theLicense.YoumayobtainacopyoftheLicenseat * *http://www.apache.org/licenses/LICENSE-2.0 * *Unlessrequiredbyapplicablelaworagreedtoinwriting,software *distributedundertheLicenseisdistributedonan"ASIS"BASIS, *WITHOUTWARRANTIESORCONDITIONSOFANYKIND,eitherexpressorimplied. *SeetheLicenseforthespecificlanguagegoverningpermissionsand *limitationsundertheLicense.
*/
/* Limit on the total --- clients will be locked out if more servers than *thisareneeded.Itisintendedsolelytokeeptheserverfromcrashing *whenthingsgetoutofhand. * *Wekeepahardmaximumnumberofservers,fortworeasons---firstoff, *incasesomethinggoesseriouslywrong,wewanttostoptheforkbomb *shortofactuallycrashingthemachinewe'rerunningonbyfillingsome *kerneltable.Secondly,itkeepsthesizeofthescoreboardfilesmall *enoughthatwecanreadthewholethingwithoutworryingtoomuchabout *theoverhead.
*/ #ifndef HARD_SERVER_LIMIT #define HARD_SERVER_LIMIT 1 #endif
staticvoid sig_term(int sig)
{ if (shutdown_pending == 1) { /* Um, is this _probably_ not an error, if the user has *triedtodoashutdowntwicequickly,sowewon't *worryaboutreportingit.
*/ return;
}
shutdown_pending = 1;
DBPRINT0 ("waiting for threads\n"); while (wait_to_finish) {
apr_thread_yield();
}
DBPRINT0 ("goodbye\n");
}
/* restart() is the signal handler for SIGHUP and SIGWINCH *intheparentprocess,unlessrunninginONE_PROCESSmode
*/ staticvoid restart(void)
{ if (restart_pending == 1) { /* Probably not an error - don't bother reporting it */ return;
}
restart_pending = 1;
is_graceful = 1;
}
for (;;) { if (shutdown_pending || restart_pending || (ap_scoreboard_image->servers[0][my_worker_num].status == WORKER_IDLE_KILL)) {
DBPRINT1 ("\nThread slot %d is shutting down\n", my_worker_num);
clean_child_exit(0, my_worker_num, ptrans, bucket_alloc);
}
/* Check the listen queue on all sockets for requests */
memcpy(&main_fds, &listenfds, sizeof(fd_set));
srv = select(listenmaxfd + 1, &main_fds, NULL, NULL, &tv);
if (srv <= 0) { if (srv < 0) {
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00217) "select() failed on listen socket");
apr_thread_yield();
} continue;
}
/* remember the last_lr we searched last time around so that
we don't end up starving any particular listening socket */ if (last_lr == NULL) {
lr = ap_listeners;
} else {
lr = last_lr->next; if (!lr)
lr = ap_listeners;
}
first_lr = lr; do {
apr_os_sock_get(&sockdes, lr->sd); if (FD_ISSET(sockdes, &main_fds)) goto got_listener;
lr = lr->next; if (!lr)
lr = ap_listeners;
} while (lr != first_lr); /* if we get here, something unexpected happened. Go back intotheselectstateandtryagain.
*/ continue;
got_listener:
last_lr = lr;
sd = lr->sd;
wouldblock_retry = MAX_WB_RETRIES;
while (wouldblock_retry) { if ((stat = apr_socket_accept(&csd, sd, ptrans)) == APR_SUCCESS) { break;
} else { /* if the error is a wouldblock then maybe we were too quicktrytopullthenextrequestfromthelisten queue.Tryafewmoretimesthenreturntoouridle
listen state. */ if (!APR_STATUS_IS_EAGAIN(stat)) { break;
}
if (wouldblock_retry--) {
apr_thread_yield();
}
}
}
/* If we got a new socket, set it to non-blocking mode and process
it. Otherwise handle the error. */ if (stat == APR_SUCCESS) {
apr_socket_opt_set(csd, APR_SO_NONBLOCK, 0); #ifdef DBINFO_ON if (wouldblock_retry < MAX_WB_RETRIES) {
retry_success++;
avg_retries += (MAX_WB_RETRIES-wouldblock_retry);
} #endif break; /* We have a socket ready for reading */
} else { #ifdef DBINFO_ON if (APR_STATUS_IS_EAGAIN(stat)) {
would_block++;
retry_fail++;
} elseif ( #else if (APR_STATUS_IS_EAGAIN(stat) || #endif
APR_STATUS_IS_ECONNRESET(stat) ||
APR_STATUS_IS_ETIMEDOUT(stat) ||
APR_STATUS_IS_EHOSTUNREACH(stat) ||
APR_STATUS_IS_ENETUNREACH(stat)) {
;
} #ifdef USE_WINSOCK elseif (APR_STATUS_IS_ENETDOWN(stat)) { /* *Whenthenetworklayerhasbeenshutdown,there *isnotmuchuseinsimplyexiting:theparent *wouldsimplyre-createus(andwe'dfailagain). *UsetheCHILDFATALcodetoteartheserverdown. *@@@Martin'sideaforpossibleimprovement: *Adifferentapproachwouldbetodefine *anewAPEXIT_NETDOWNexitcode,thereception *ofwhichwouldmaketheparentshutdownall *children,thenidle-loopuntilitdetectedthat *thenetworkisupagain,andrestartthechildren. *BenHydenotedthattemporaryENETDOWNsituations *occurinmobileIP.
*/
ap_log_error(APLOG_MARK, APLOG_EMERG, stat, ap_server_conf, APLOGNO(00218) "apr_socket_accept: giving up.");
clean_child_exit(APEXIT_CHILDFATAL, my_worker_num, ptrans,
bucket_alloc);
} #endif else {
ap_log_error(APLOG_MARK, APLOG_ERR, stat, ap_server_conf, APLOGNO(00219) "apr_socket_accept: (client socket)");
clean_child_exit(1, my_worker_num, ptrans, bucket_alloc);
}
}
}
staticvoid perform_idle_server_maintenance(apr_pool_t *p)
{ int i; int idle_count;
worker_score *ws; int free_length; int free_slots[MAX_SPAWN_RATE]; int last_non_dead; int total_non_dead;
for (i = 0; i < ap_threads_limit; ++i) { int status;
if (i >= ap_max_workers_limit && free_length == idle_spawn_rate) break;
ws = &ap_scoreboard_image->servers[0][i];
status = ws->status; if (status == WORKER_DEAD) { /* try to keep children numbers as low as possible */ if (free_length < idle_spawn_rate) {
free_slots[free_length] = i;
++free_length;
}
} elseif (status == WORKER_IDLE_KILL) { /* If it is already marked to die, skip it */ continue;
} else { /* We consider a starting server as idle because we started it *atleastacycleago,andifitstillhasn'tfinishedstarting *thenwe'rejustgoingtoswampthingsworsebyforkingmore. *Sowehopefullywon'tneedtoforkmoreifwecountit. *ThisdependsontheorderingofSERVER_READYandSERVER_STARTING.
*/ if (status <= WORKER_READY) {
++ idle_count;
}
++total_non_dead;
last_non_dead = i;
}
}
DBPRINT2("Total: %d Idle Count: %d \r", total_non_dead, idle_count);
ap_max_workers_limit = last_non_dead + 1; if (idle_count > ap_threads_max_free) { /* kill off one child... we use the pod because that'll cause it to *shutdowngracefully,incaseithappenedtopickuparequest *whilewewerecounting
*/
idle_spawn_rate = 1;
ap_update_child_status_from_indexes(0, last_non_dead, WORKER_IDLE_KILL,
(request_rec *) NULL);
DBPRINT1("\nKilling idle thread: %d\n", last_non_dead);
} elseif (idle_count < ap_threads_min_free) { /* terminate the free list */ if (free_length == 0) { /* only report this condition once */ staticint reported = 0;
if (!reported) {
ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf, APLOGNO(00220) "server reached MaxRequestWorkers setting, consider" " raising the MaxRequestWorkers setting");
reported = 1;
}
idle_spawn_rate = 1;
} else { if (idle_spawn_rate >= 8) {
ap_log_error(APLOG_MARK, APLOG_INFO, 0, ap_server_conf, APLOGNO(00221) "server seems busy, (you may need " "to increase StartServers, or Min/MaxSpareServers), " "spawning %d children, there are %d idle, and " "%d total children", idle_spawn_rate,
idle_count, total_non_dead);
}
DBPRINT0("\n"); for (i = 0; i < free_length; ++i) {
DBPRINT1("Spawning additional thread slot: %d\n", free_slots[i]);
make_child(ap_server_conf, free_slots[i]);
} /* the next time around we want to spawn twice as many if this *wasn'tgoodenough,butnotifwe'vejustdoneagraceful
*/ if (hold_off_on_exponential_spawning) {
--hold_off_on_exponential_spawning;
} elseif (idle_spawn_rate < MAX_SPAWN_RATE) {
idle_spawn_rate *= 2;
}
}
} else {
idle_spawn_rate = 1;
}
}
staticvoid display_settings()
{ int status_array[SERVER_NUM_STATUS]; int i, status, total=0; int reqs = request_count; #ifdef DBINFO_ON int wblock = would_block;
printf("%s\n", ap_get_server_description()); if (ap_my_addrspace && (ap_my_addrspace[0] != 'O') && (ap_my_addrspace[1] != 'S'))
printf(" Running in address space %s\n", ap_my_addrspace);
/* Display listening ports */
printf(" Listening on port(s):");
lr = ap_listeners; do {
printf(" %d", lr->bind_addr->port);
lr = lr->next;
} while (lr && lr != ap_listeners);
if (!is_graceful) { if (ap_run_pre_mpm(s->process->pool, SB_NOT_SHARED) != OK) { return !OK;
}
}
/* Only set slot 0 since that is all NetWare will ever have. */
ap_scoreboard_image->parent[0].pid = getpid();
ap_scoreboard_image->parent[0].generation = ap_my_generation;
ap_run_child_status(ap_server_conf,
ap_scoreboard_image->parent[0].pid,
ap_my_generation, 0,
MPM_CHILD_STARTED);
/* Allow the Apache screen to be closed normally on exit() only if it hasnotbeenexplicitlyforcedtocloseonexit().(ie.the-Eflag
was specified at startup) */ if (hold_screen_on_exit > 0) {
hold_screen_on_exit = 0;
}
/* Shutdown the listen sockets so that we don't get stuck in a blocking call.
shutdown_listeners();*/
if (shutdown_pending) { /* Got an unload from the console */
ap_log_error(APLOG_MARK, APLOG_NOTICE, 0, ap_server_conf, APLOGNO(00226) "caught SIGTERM, shutting down");
while (worker_thread_count > 0) {
printf ("\rShutdown pending. Waiting for %lu thread(s) to terminate...",
worker_thread_count);
apr_thread_yield();
}
mpm_main_cleanup(); return DONE;
} else { /* the only other way out is a restart */ /* advance to the next generation */ /* XXX: we really need to make sure this new generation number isn't in *usebyanyofthechildren.
*/
++ap_my_generation;
ap_scoreboard_image->global->running_generation = ap_my_generation;
/* Wait for all of the threads to terminate before initiating the restart */ while (worker_thread_count > 0) {
printf ("\rRestart pending. Waiting for %lu thread(s) to terminate...",
worker_thread_count);
apr_thread_yield();
}
printf ("\nRestarting...\n");
}
/* we want this only the first time around */ if (restart_num++ == 0) {
startup = 1;
}
if (ap_threads_limit > HARD_THREAD_LIMIT) { if (startup) {
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00228) "WARNING: MaxThreads of %d exceeds compile-time " "limit of %d threads, decreasing to %d. " "To increase, please see the HARD_THREAD_LIMIT " "define in server/mpm/netware%s.",
ap_threads_limit, HARD_THREAD_LIMIT, HARD_THREAD_LIMIT,
MPM_HARD_LIMITS_FILE);
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00229) "MaxThreads of %d exceeds compile-time limit " "of %d, decreasing to match",
ap_threads_limit, HARD_THREAD_LIMIT);
}
ap_threads_limit = HARD_THREAD_LIMIT;
} elseif (ap_threads_limit < 1) { if (startup) {
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00230) "WARNING: MaxThreads of %d not allowed, " "increasing to 1.", ap_threads_limit);
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(02661) "MaxThreads of %d not allowed, increasing to 1",
ap_threads_limit);
}
ap_threads_limit = 1;
}
/* ap_threads_to_start > ap_threads_limit effectively checked in *calltostartup_workers(ap_threads_to_start)inap_mpm_run()
*/ if (ap_threads_to_start < 0) { if (startup) {
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00231) "WARNING: StartThreads of %d not allowed, " "increasing to 1.", ap_threads_to_start);
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00232) "StartThreads of %d not allowed, increasing to 1",
ap_threads_to_start);
}
ap_threads_to_start = 1;
}
if (ap_threads_min_free < 1) { if (startup) {
ap_log_error(APLOG_MARK, APLOG_WARNING | APLOG_STARTUP, 0, NULL, APLOGNO(00233) "WARNING: MinSpareThreads of %d not allowed, " "increasing to 1 to avoid almost certain server failure. " "Please read the documentation.", ap_threads_min_free);
} else {
ap_log_error(APLOG_MARK, APLOG_WARNING, 0, s, APLOGNO(00234) "MinSpareThreads of %d not allowed, increasing to 1",
ap_threads_min_free);
}
ap_threads_min_free = 1;
}
/* ap_threads_max_free < ap_threads_min_free + 1 checked in ap_mpm_run() */
return OK;
}
staticvoid netware_mpm_hooks(apr_pool_t *p)
{ /* Run the pre-config hook after core's so that it can override the *defaultsettingofThreadStackSizeforNetWare.
*/ staticconstchar * const predecessors[] = {"core.c", NULL};
/* Make sure to hold the Apache screen open if exit() is called */
hold_screen_on_exit = 1;
/* Rewrite process->argv[]; * *adddefault-dserverrootfromthepathofthisexecutable * *Theendresultwilllooklike: *The-dserverrootdefaultfromtherunningexecutable
*/ if (process->argc > 0) { char *s = apr_pstrdup (process->pconf, process->argv[0]); if (s) { int i, len = strlen(s);
for (i=len; i; i--) { if (s[i] == '\\' || s[i] == '/') {
s[i] = '\0';
apr_filepath_merge(&def_server_root, NULL, s,
APR_FILEPATH_TRUENAME, process->pool); break;
}
} /* Use process->pool so that the rewritten argv *lastsforthelifetimeoftheserverprocess, *becausepconfwillbedestroyedafterthe *initialpre-flightoftheconfigparser.
*/
mpm_new_argv = apr_array_make(process->pool, process->argc + 2, sizeof(constchar *));
*(constchar **)apr_array_push(mpm_new_argv) = process->argv[0];
*(constchar **)apr_array_push(mpm_new_argv) = "-d";
*(constchar **)apr_array_push(mpm_new_argv) = def_server_root;
optbuf[0] = '-';
optbuf[2] = '\0';
apr_getopt_init(&opt, process->pool, process->argc, process->argv); while (apr_getopt(opt, AP_SERVER_BASEARGS"n:", optbuf + 1, &opt_arg) == APR_SUCCESS) { switch (optbuf[1]) { case'n': if (opt_arg) {
renamescreen(opt_arg);
} break; case'E': /* Don't need to hold the screen open if the output is going to a file */
hold_screen_on_exit = -1; default:
*(constchar **)apr_array_push(mpm_new_argv) =
apr_pstrdup(process->pool, optbuf);
if (!strnicmp(szCommand, szcommandLine, iCommandLen)) {
ActivateScreen (getscreenhandle());
/* If an instance id was not given but the nlm is loaded in protectedspace,thenthecommandbelongstothe
OS address space instance to pass it on. */
pID = strstr (szcommandLine, "-p"); if ((pID == NULL) && nlmisloadedprotected()) return NOTMYCOMMAND;
/* If we got an instance id but it doesn't match this
instance of the nlm, pass it on. */ if (pID) {
pID = &pID[2]; while (*pID && (*pID == ' '))
pID++;
} if (pID && ap_my_addrspace && strnicmp(pID, ap_my_addrspace, strlen(ap_my_addrspace))) return NOTMYCOMMAND;
/* If we have determined that this command belongs to this
instance of the nlm, then handle it. */ if (!strnicmp("RESTART",&szcommandLine[iCommandLen],3)) {
printf("Restart Requested...\n");
restart();
} elseif (!strnicmp("VERSION",&szcommandLine[iCommandLen],3)) {
printf("Server version: %s\n", ap_get_server_description());
printf("Server built: %s\n", ap_get_server_built());
} elseif (!strnicmp("MODULES",&szcommandLine[iCommandLen],3)) {
ap_show_modules();
} elseif (!strnicmp("DIRECTIVES",&szcommandLine[iCommandLen],3)) {
ap_show_directives();
} elseif (!strnicmp("SHUTDOWN",&szcommandLine[iCommandLen],3)) {
printf("Shutdown Requested...\n");
shutdown_pending = 1;
} elseif (!strnicmp("SETTINGS",&szcommandLine[iCommandLen],3)) { if (show_settings) {
show_settings = 0;
ClearScreen (getscreenhandle());
show_server_data();
} else {
show_settings = 1;
display_settings();
}
} else {
show_settings = 0; if (strnicmp("HELP",&szcommandLine[iCommandLen],3))
printf("Unknown APACHE2 command %s\n", &szcommandLine[iCommandLen]);
printf("Usage: APACHE2 [command] [-p <instance ID>]\n");
printf("Commands:\n");
printf("\tDIRECTIVES - Show directives\n");
printf("\tHELP - Display this help information\n");
printf("\tMODULES - Show a list of the loaded modules\n");
printf("\tRESTART - Reread the configuration file and restart Apache\n");
printf("\tSETTINGS - Show current thread status\n");
printf("\tSHUTDOWN - Shutdown Apache\n");
printf("\tVERSION - Display the server version information\n");
}
/* Tell NetWare we handled the command */ return HANDLEDCOMMAND;
}
/* Tell NetWare that the command isn't mine */ return NOTMYCOMMAND;
}
staticint InstallConsoleHandler(void)
{ /* Our command line handler interfaces the system operator
with this NLM */
staticconst command_rec netware_mpm_cmds[] = {
LISTEN_COMMANDS,
AP_INIT_TAKE1("StartThreads", set_threads_to_start, NULL, RSRC_CONF, "Number of worker threads launched at server startup"),
AP_INIT_TAKE1("MinSpareThreads", set_min_free_threads, NULL, RSRC_CONF, "Minimum number of idle threads, to handle request spikes"),
AP_INIT_TAKE1("MaxSpareThreads", set_max_free_threads, NULL, RSRC_CONF, "Maximum number of idle threads"),
AP_INIT_TAKE1("MaxThreads", set_thread_limit, NULL, RSRC_CONF, "Maximum number of worker threads alive at the same time"),
{ NULL }
};
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.32Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-28)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.