context: Add a new API to raise and restore NOFILE limits
Wayland, especially when using SHM buffers, can use a lot of file descriptors and can possibly reach the NOFILE soft limit. Add a new API to MetaContext to raise and restore the NOFILE limit so that the Wayland compositor can use as many file descriptors as the hard limit allows. See-also: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1283 Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2235>
This commit is contained in:
parent
38f3bf6ee2
commit
8b9341131a
@ -23,6 +23,7 @@
|
|||||||
#include "core/meta-context-private.h"
|
#include "core/meta-context-private.h"
|
||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include <sys/resource.h>
|
||||||
|
|
||||||
#include "backends/meta-backend-private.h"
|
#include "backends/meta-backend-private.h"
|
||||||
#include "compositor/meta-plugin-manager.h"
|
#include "compositor/meta-plugin-manager.h"
|
||||||
@ -77,6 +78,9 @@ typedef struct _MetaContextPrivate
|
|||||||
|
|
||||||
GMainLoop *main_loop;
|
GMainLoop *main_loop;
|
||||||
GError *termination_error;
|
GError *termination_error;
|
||||||
|
#ifdef RLIMIT_NOFILE
|
||||||
|
struct rlimit saved_rlimit_nofile;
|
||||||
|
#endif
|
||||||
} MetaContextPrivate;
|
} MetaContextPrivate;
|
||||||
|
|
||||||
G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT)
|
G_DEFINE_TYPE_WITH_PRIVATE (MetaContext, meta_context, G_TYPE_OBJECT)
|
||||||
@ -492,6 +496,108 @@ meta_context_set_unsafe_mode (MetaContext *context,
|
|||||||
g_object_notify_by_pspec (G_OBJECT (context), obj_props[PROP_UNSAFE_MODE]);
|
g_object_notify_by_pspec (G_OBJECT (context), obj_props[PROP_UNSAFE_MODE]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
meta_context_save_rlimit_nofile (MetaContext *context,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
#ifdef RLIMIT_NOFILE
|
||||||
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
||||||
|
|
||||||
|
if (getrlimit (RLIMIT_NOFILE, &priv->saved_rlimit_nofile) != 0)
|
||||||
|
{
|
||||||
|
priv->saved_rlimit_nofile.rlim_cur = 0;
|
||||||
|
priv->saved_rlimit_nofile.rlim_max = 0;
|
||||||
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
||||||
|
"getrlimit failed: %s", g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
#else
|
||||||
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS,
|
||||||
|
"Missing support for RLIMIT_NOFILE");
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_context_raise_rlimit_nofile:
|
||||||
|
* @context: a #MetaContext
|
||||||
|
* @error: a return location for errors
|
||||||
|
*
|
||||||
|
* Raises the RLIMIT_NOFILE limit value to the hard limit.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
meta_context_raise_rlimit_nofile (MetaContext *context,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
#ifdef RLIMIT_NOFILE
|
||||||
|
struct rlimit new_rlimit;
|
||||||
|
|
||||||
|
if (getrlimit (RLIMIT_NOFILE, &new_rlimit) != 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
||||||
|
"getrlimit failed: %s", g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Raise the rlimit_nofile value to the hard limit */
|
||||||
|
new_rlimit.rlim_cur = new_rlimit.rlim_max;
|
||||||
|
|
||||||
|
if (setrlimit (RLIMIT_NOFILE, &new_rlimit) != 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
||||||
|
"setrlimit failed: %s", g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
#else
|
||||||
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS,
|
||||||
|
"Missing support for RLIMIT_NOFILE");
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* meta_context_restore_rlimit_nofile:
|
||||||
|
* @context: a #MetaContext
|
||||||
|
* @error: a return location for errors
|
||||||
|
*
|
||||||
|
* Restores the RLIMIT_NOFILE limits from when the #MetaContext was created.
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
meta_context_restore_rlimit_nofile (MetaContext *context,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
#ifdef RLIMIT_NOFILE
|
||||||
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
||||||
|
|
||||||
|
if (priv->saved_rlimit_nofile.rlim_cur == 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOENT,
|
||||||
|
"RLIMIT_NOFILE not saved");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setrlimit (RLIMIT_NOFILE, &priv->saved_rlimit_nofile) != 0)
|
||||||
|
{
|
||||||
|
g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (errno),
|
||||||
|
"setrlimit failed: %s", g_strerror (errno));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
#else
|
||||||
|
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS,
|
||||||
|
"Missing support for RLIMIT_NOFILE");
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
meta_context_get_property (GObject *object,
|
meta_context_get_property (GObject *object,
|
||||||
guint prop_id,
|
guint prop_id,
|
||||||
@ -618,6 +724,7 @@ static void
|
|||||||
meta_context_init (MetaContext *context)
|
meta_context_init (MetaContext *context)
|
||||||
{
|
{
|
||||||
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
MetaContextPrivate *priv = meta_context_get_instance_private (context);
|
||||||
|
g_autoptr (GError) error = NULL;
|
||||||
|
|
||||||
priv->plugin_gtype = G_TYPE_NONE;
|
priv->plugin_gtype = G_TYPE_NONE;
|
||||||
priv->gnome_wm_keybindings = g_strdup ("Mutter");
|
priv->gnome_wm_keybindings = g_strdup ("Mutter");
|
||||||
@ -631,4 +738,10 @@ meta_context_init (MetaContext *context)
|
|||||||
g_option_context_set_main_group (priv->option_context,
|
g_option_context_set_main_group (priv->option_context,
|
||||||
g_option_group_new (NULL, NULL, NULL,
|
g_option_group_new (NULL, NULL, NULL,
|
||||||
context, NULL));
|
context, NULL));
|
||||||
|
|
||||||
|
if (!meta_context_save_rlimit_nofile (context, &error))
|
||||||
|
{
|
||||||
|
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOSYS))
|
||||||
|
g_warning ("Failed to save the nofile limit: %s", error->message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,4 +98,12 @@ MetaBackend * meta_context_get_backend (MetaContext *context);
|
|||||||
META_EXPORT
|
META_EXPORT
|
||||||
MetaDisplay * meta_context_get_display (MetaContext *context);
|
MetaDisplay * meta_context_get_display (MetaContext *context);
|
||||||
|
|
||||||
|
META_EXPORT
|
||||||
|
gboolean meta_context_raise_rlimit_nofile (MetaContext *context,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
META_EXPORT
|
||||||
|
gboolean meta_context_restore_rlimit_nofile (MetaContext *context,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
#endif /* META_CONTEXT_H */
|
#endif /* META_CONTEXT_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user