Move scriptlet priority reset to a plugin

Resetting priorities against daemons inheriting nice'd properties
from rpm is a workaround needed only on legacy SysV init systems,
but in systemd era this is nothing but counter-productive. So make
the functionality optional by moving it into a plugin.

This probably breaks the testcase because now we'd somehow need to
determine from the testsuite whether the plugin will be loaded or not,
but since the test is only enabled as root ... maybe its not that big
a deal.
This commit is contained in:
Panu Matilainen 2017-03-10 12:12:00 +02:00
parent 22260d3580
commit 86c523da6f
4 changed files with 55 additions and 26 deletions

View File

@ -337,32 +337,6 @@ static rpmRC runExtScript(rpmPlugins plugins, ARGV_const_t prefixes,
fclose(in);
dup2(inpipe[0], STDIN_FILENO);
/* If RPM was invoked with nice and/or ionice, the scripts that we run
* will be also nice'd/ionice'd. This is terrible if you restart any
* daemon (e.g. mysqld), so let's reset this to default values before
* taking any actions.
*/
/* Call for resetting nice priority. */
int ret;
ret = setpriority(PRIO_PROCESS, 0, 0);
if (ret == -1) {
rpmlog(RPMLOG_WARNING, _("Unable to reset nice value: %s"),
strerror(errno));
}
/* Call for resetting IO priority. */
#if defined(__linux__)
/* Defined at include/linux/ioprio.h */
const int _IOPRIO_WHO_PROCESS = 1;
const int _IOPRIO_CLASS_NONE = 0;
ret = syscall(SYS_ioprio_set, _IOPRIO_WHO_PROCESS, 0, _IOPRIO_CLASS_NONE);
if (ret == -1) {
rpmlog(RPMLOG_WARNING, _("Unable to reset I/O priority: %s"),
strerror(errno));
}
#endif
/* Run scriptlet post fork hook for all plugins */
if (rpmpluginsCallScriptletForkPost(plugins, *argvp[0], RPMSCRIPTLET_FORK | RPMSCRIPTLET_EXEC) != RPMRC_FAIL) {
doScriptExec(*argvp, prefixes, scriptFd, out);

View File

@ -1089,6 +1089,7 @@ package or when debugging this package.\
%__transaction_selinux %{__plugindir}/selinux.so
%__transaction_syslog %{__plugindir}/syslog.so
%__transaction_ima %{__plugindir}/ima.so
%__transaction_prioreset %{__plugindir}/prioreset.so
#------------------------------------------------------------------------------
# Macros for further automated spec %setup and patch application

View File

@ -29,6 +29,10 @@ systemd_inhibit_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/
plugins_LTLIBRARIES += systemd_inhibit.la
endif
prioreset_la_SOURCES = prioreset.c
prioreset_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
plugins_LTLIBRARIES += prioreset.la
syslog_la_SOURCES = syslog.c
syslog_la_LIBADD = $(top_builddir)/lib/librpm.la $(top_builddir)/rpmio/librpmio.la
plugins_LTLIBRARIES += syslog.la

50
plugins/prioreset.c Normal file
View File

@ -0,0 +1,50 @@
#include "system.h"
#include <errno.h>
#include <sys/resource.h>
#if defined(__linux__)
#include <sys/syscall.h> /* For ionice */
#endif
#include <rpm/rpmlog.h>
#include "lib/rpmplugin.h"
#include "debug.h"
/*
* In general we want scriptlets to run with the same priority as rpm
* itself. However on legacy SysV init systems, properties of the
* parent process can be inherited by the actual daemons on restart,
* so you can end up with eg nice/ionice'd mysql or httpd, ouch.
* This plugin resets the scriptlet process priorities after forking, and
* can be used to counter that effect. Should not be used with systemd
* because the it's not needed there, and the effect is counter-productive.
*/
static rpmRC prioreset_scriptlet_fork_post(rpmPlugin plugin, const char *path, int type)
{
/* Call for resetting nice priority. */
int ret = setpriority(PRIO_PROCESS, 0, 0);
if (ret == -1) {
rpmlog(RPMLOG_WARNING, _("Unable to reset nice value: %s"),
strerror(errno));
}
/* Call for resetting IO priority. */
#if defined(__linux__)
/* Defined at include/linux/ioprio.h */
const int _IOPRIO_WHO_PROCESS = 1;
const int _IOPRIO_CLASS_NONE = 0;
ret = syscall(SYS_ioprio_set, _IOPRIO_WHO_PROCESS, 0, _IOPRIO_CLASS_NONE);
if (ret == -1) {
rpmlog(RPMLOG_WARNING, _("Unable to reset I/O priority: %s"),
strerror(errno));
}
#endif
return RPMRC_OK;
}
struct rpmPluginHooks_s prioreset_hooks = {
.scriptlet_fork_post = prioreset_scriptlet_fork_post,
};