Skip to content

Add cgroups support to PHP-FPM pools #2440

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions sapi/fpm/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,9 @@ if test "$PHP_FPM" != "no"; then
PHP_ARG_WITH(fpm-acl,,
[ --with-fpm-acl Use POSIX Access Control Lists], no, no)

PHP_ARG_WITH(fpm-cgroup,,
[ --with-fpm-cgroup Use CGroups], no, no)

if test "$PHP_FPM_SYSTEMD" != "no" ; then
if test -z "$PKG_CONFIG"; then
AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
Expand Down Expand Up @@ -638,6 +641,17 @@ if test "$PHP_FPM" != "no"; then
])
fi

if test "$PHP_FPM_CGROUP" != "no" ; then
AC_CHECK_HEADERS([libcgroup.h])
AC_CHECK_LIB(cgroup, cgroup_init, [
PHP_ADD_LIBRARY(cgroup)
AC_DEFINE(HAVE_FPM_CGROUP, 1, [ CGroups support ])
],[
AC_MSG_ERROR(libcgroup required not found)
])
fi


PHP_SUBST_OLD(php_fpm_systemd)
AC_DEFINE_UNQUOTED(PHP_FPM_SYSTEMD, "$php_fpm_systemd", [fpm systemd service type])

Expand Down
9 changes: 9 additions & 0 deletions sapi/fpm/fpm/fpm_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,9 @@ static struct ini_value_parser_s ini_fpm_pool_options[] = {
{ "security.limit_extensions", &fpm_conf_set_string, WPO(security_limit_extensions) },
#ifdef HAVE_APPARMOR
{ "apparmor_hat", &fpm_conf_set_string, WPO(apparmor_hat) },
#endif
#ifdef HAVE_FPM_CGROUP
{ "cgroup", &fpm_conf_set_string, WPO(cgroup) },
#endif
{ 0, 0, 0 }
};
Expand Down Expand Up @@ -658,6 +661,9 @@ int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc) /* {{{ */
#ifdef HAVE_APPARMOR
free(wpc->apparmor_hat);
#endif
#ifdef HAVE_FPM_CGROUP
free(wpc->cgroup);
#endif

for (kv = wpc->php_values; kv; kv = kv_next) {
kv_next = kv->next;
Expand Down Expand Up @@ -1606,6 +1612,9 @@ static void fpm_conf_dump() /* {{{ */
zlog(ZLOG_NOTICE, "\tprefix = %s", STR2STR(wp->config->prefix));
zlog(ZLOG_NOTICE, "\tuser = %s", STR2STR(wp->config->user));
zlog(ZLOG_NOTICE, "\tgroup = %s", STR2STR(wp->config->group));
#ifdef HAVE_FPM_CGROUP
zlog(ZLOG_NOTICE, "\tcgroup = %s", STR2STR(wp->config->cgroup));
#endif
zlog(ZLOG_NOTICE, "\tlisten = %s", STR2STR(wp->config->listen_address));
zlog(ZLOG_NOTICE, "\tlisten.backlog = %d", wp->config->listen_backlog);
#ifdef HAVE_FPM_ACL
Expand Down
3 changes: 3 additions & 0 deletions sapi/fpm/fpm/fpm_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ struct fpm_worker_pool_config_s {
char *listen_acl_users;
char *listen_acl_groups;
#endif
#ifdef HAVE_FPM_CGROUP
char *cgroup;
#endif
};

struct ini_value_parser_s {
Expand Down
52 changes: 52 additions & 0 deletions sapi/fpm/fpm/fpm_unix.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
#include <sys/acl.h>
#endif

#ifdef HAVE_FPM_CGROUP
#include <libcgroup.h>
#endif

#include "fpm.h"
#include "fpm_conf.h"
#include "fpm_cleanup.h"
Expand Down Expand Up @@ -322,6 +326,33 @@ static int fpm_unix_conf_wp(struct fpm_worker_pool_s *wp) /* {{{ */
wp->home = strdup(pwd->pw_dir);
}
}
#ifdef HAVE_FPM_CGROUP
if (wp->config->cgroup && *wp->config->cgroup) {
wp->cgroup = cgroup_new_cgroup(wp->config->cgroup);
if (wp->cgroup == NULL) {
zlog(ZLOG_ERROR, "[pool %s] cannot init cgroup structure", wp->config->name);
return -1;
}

int ret = cgroup_get_cgroup(wp->cgroup);
if (ret != 0) {
zlog(ZLOG_ERROR, "[pool %s] cannot read cgroup '%s': %s.", wp->config->name, wp->config->cgroup, cgroup_strerror(ret));
return -1;
}

if (!is_root) {
uid_t tasks_uid, control_uid;
gid_t tasks_gid, control_gid;
cgroup_get_uid_gid(wp->cgroup, &tasks_uid, &tasks_gid, &control_uid, &control_gid);

/* We also need to check file mode, but libcgroup does not provide the way to get it.
* So continue to proceed with a notice. */
if (tasks_uid != geteuid() && tasks_gid != getegid()) {
zlog(ZLOG_NOTICE, "[pool %s] may have no access to cgroup '%s'.", wp->config->name, wp->config->cgroup);
}
}
}
#endif
return 0;
}
/* }}} */
Expand Down Expand Up @@ -370,6 +401,16 @@ int fpm_unix_init_child(struct fpm_worker_pool_s *wp) /* {{{ */
}
}

#ifdef HAVE_FPM_CGROUP
if (wp->cgroup) {
int ret = cgroup_attach_task(wp->cgroup);
if (ret != 0) {
zlog(ZLOG_SYSERROR, "[pool %s] failed change cgroup to (%s): %s.", wp->config->name, wp->config->cgroup, cgroup_strerror(ret));
return -1;
}
}
#endif

if (is_root) {

if (wp->config->process_priority != 64) {
Expand Down Expand Up @@ -569,6 +610,17 @@ int fpm_unix_init_main() /* {{{ */
}
}

#ifdef HAVE_FPM_CGROUP
for (wp = fpm_worker_all_pools; wp && !(wp->config->cgroup && *wp->config->cgroup); wp = wp->next);
if (wp) {
int ret = cgroup_init();
if (ret != 0) {
zlog(ZLOG_SYSERROR, "libcgroup initialization failed: %s", cgroup_strerror(ret));
return -1;
}
}
#endif

fpm_globals.parent_pid = getpid();
for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
if (0 > fpm_unix_conf_wp(wp)) {
Expand Down
3 changes: 3 additions & 0 deletions sapi/fpm/fpm/fpm_worker_pool.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ void fpm_worker_pool_free(struct fpm_worker_pool_s *wp) /* {{{ */
if (wp->home) {
free(wp->home);
}
#ifdef HAVE_FPM_CGROUP
cgroup_free(&wp->cgroup);
#endif
fpm_unix_free_socket_premissions(wp);
free(wp);
}
Expand Down
7 changes: 7 additions & 0 deletions sapi/fpm/fpm/fpm_worker_pool.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
#include "fpm_conf.h"
#include "fpm_shm.h"

#ifdef HAVE_FPM_CGROUP
#include <libcgroup.h>
#endif

struct fpm_worker_pool_s;
struct fpm_child_s;
struct fpm_child_stat_s;
Expand Down Expand Up @@ -46,6 +50,9 @@ struct fpm_worker_pool_s {
#ifdef HAVE_FPM_ACL
void *socket_acl;
#endif
#ifdef HAVE_FPM_CGROUP
struct cgroup *cgroup;
#endif
};

struct fpm_worker_pool_s *fpm_worker_pool_alloc();
Expand Down
5 changes: 5 additions & 0 deletions sapi/fpm/www.conf.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
user = @php_fpm_user@
group = @php_fpm_group@

; When Cgroups are supported you can use this option to put worker processes to
; specified cgroup.
; Default Value: no set
;cgroup = webserver/fpm

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
; 'ip.add.re.ss:port' - to listen on a TCP socket to a specific IPv4 address on
Expand Down