Support a per-location nice value. Note that since we now have two different settings in the per-dir configuration, we need to introduce a merge function. Index: httpd-2.2.11/server/mpm/experimental/itk/itk.c =================================================================== --- httpd-2.2.11.orig/server/mpm/experimental/itk/itk.c 2009-04-14 23:29:16.000000000 +0200 +++ httpd-2.2.11/server/mpm/experimental/itk/itk.c 2009-04-14 23:31:05.000000000 +0200 @@ -156,11 +156,14 @@ static volatile int die_now = 0; +#define UNSET_NICE_VALUE 100 + typedef struct { uid_t uid; gid_t gid; char *username; + int nice_value; } itk_per_dir_conf; typedef struct @@ -511,6 +514,7 @@ CAP_SETUID, CAP_SETGID, CAP_DAC_READ_SEARCH, + CAP_SYS_NICE, }; #endif @@ -1444,6 +1448,12 @@ strncpy(ap_scoreboard_image->servers[my_child_num][0].vhost, r->server->server_hostname, 31); ap_scoreboard_image->servers[my_child_num][0].vhost[31] = 0; + if (dconf->nice_value != UNSET_NICE_VALUE && + setpriority(PRIO_PROCESS, 0, dconf->nice_value)) { + _DBG("setpriority(): %s", strerror(errno)); + err = 1; + } + wanted_uid = dconf->uid; wanted_gid = dconf->gid; wanted_username = dconf->username; @@ -1454,7 +1464,7 @@ wanted_username = unixd_config.user_name; } - if (wanted_uid != -1 && wanted_gid != -1 && (getuid() != wanted_uid || getgid() != wanted_gid)) { + if (!err && wanted_uid != -1 && wanted_gid != -1 && (getuid() != wanted_uid || getgid() != wanted_gid)) { if (setgid(wanted_gid)) { _DBG("setgid(%d): %s", wanted_gid, strerror(errno)); err = 1; @@ -1474,7 +1484,7 @@ */ if (err) { ap_log_error(APLOG_MARK, APLOG_WARNING, 0, NULL, \ - "Couldn't set uid/gid, closing connection."); + "Couldn't set uid/gid/priority, closing connection."); ap_lingering_close(r->connection); exit(0); } @@ -1630,6 +1640,27 @@ return NULL; } +static const char *set_nice_value (cmd_parms *cmd, void *ptr, const char *arg) +{ + itk_per_dir_conf *dconf = (itk_per_dir_conf *) ptr; + int nice_value = atoi(arg); + + if (nice_value < -20) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, + "WARNING: NiceValue of %d is below -20, increasing NiceValue to -20.", + nice_value); + nice_value = -20; + } + else if (nice_value > 19) { + ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, + "WARNING: NiceValue of %d is above 19, lowering NiceValue to 19.", + nice_value); + nice_value = 19; + } + dconf->nice_value = nice_value; + return NULL; +} + static const command_rec itk_cmds[] = { UNIX_DAEMON_COMMANDS, LISTEN_COMMANDS, @@ -1647,6 +1678,8 @@ "Tie a virtual host to a specific child process."), AP_INIT_TAKE1("MaxClientsVHost", set_max_clients_vhost, NULL, RSRC_CONF, "Maximum number of children alive at the same time for this virtual host."), +AP_INIT_TAKE1("NiceValue", set_nice_value, NULL, RSRC_CONF|ACCESS_CONF, + "Set nice value for the given vhost, from -20 (highest priority) to 19 (lowest priority)."), AP_GRACEFUL_SHUTDOWN_TIMEOUT_COMMAND, { NULL } }; @@ -1657,6 +1690,32 @@ itk_per_dir_conf *c = (itk_per_dir_conf *) apr_pcalloc(p, sizeof(itk_per_dir_conf)); c->uid = c->gid = -1; + c->nice_value = UNSET_NICE_VALUE; + return c; +} + +/* == merge the parent per-dir config structure into ours == */ +static void *itk_merge_dir_config(apr_pool_t *p, void *parent_ptr, void *child_ptr) +{ + itk_per_dir_conf *c = (itk_per_dir_conf *) + apr_pcalloc(p, sizeof(itk_per_dir_conf)); + itk_per_dir_conf *parent = (itk_per_dir_conf *) parent_ptr; + itk_per_dir_conf *child = (itk_per_dir_conf *) child_ptr; + + if (child->username != NULL) { + c->username = apr_pstrdup(p, child->username); + c->uid = child->uid; + c->gid = child->gid; + } else if (parent->username != NULL) { + c->username = apr_pstrdup(p, parent->username); + c->uid = parent->uid; + c->gid = parent->gid; + } + if (child->nice_value != UNSET_NICE_VALUE) { + c->nice_value = child->nice_value; + } else { + c->nice_value = parent->nice_value; + } return c; } @@ -1673,7 +1732,7 @@ MPM20_MODULE_STUFF, ap_mpm_rewrite_args, /* hook to run before apache parses args */ itk_create_dir_config, /* create per-directory config structure */ - NULL, /* merge per-directory config structures */ + itk_merge_dir_config, /* merge per-directory config structures */ itk_create_server_config, /* create per-server config structure */ NULL, /* merge per-server config structures */ itk_cmds, /* command apr_table_t */