diff --git a/CMakeLists.txt b/CMakeLists.txt index 360357890d..2b2ef8ccf5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -279,6 +279,13 @@ set_package_properties(Xwayland PROPERTIES PURPOSE "Needed for running kwin_wayland" ) +find_package(Libcap) +set_package_properties(Libcap PROPERTIES + TYPE OPTIONAL + PURPOSE "Needed for running kwin_wayland with real-time scheduling policy" +) +set(HAVE_LIBCAP ${Libcap_FOUND}) + ########### configure tests ############### include(CMakeDependentOption) @@ -339,6 +346,11 @@ add_feature_info("linux/fb.h" HAVE_LINUX_FB_H "Required for the fbdev backend") +check_symbol_exists(SCHED_RESET_ON_FORK "sched.h" HAVE_SCHED_RESET_ON_FORK) +add_feature_info("SCHED_RESET_ON_FORK" + HAVE_SCHED_RESET_ON_FORK + "Required for running kwin_wayland with real-time scheduling") + ########### global ############### set(kwin_effects_dbus_xml ${CMAKE_CURRENT_SOURCE_DIR}/org.kde.kwin.Effects.xml) @@ -624,8 +636,20 @@ install(TARGETS kwin_x11 ${INSTALL_TARGETS_DEFAULT_ARGS} ) add_executable(kwin_wayland main_wayland.cpp) target_link_libraries(kwin_wayland kwin) +if (HAVE_LIBCAP) + target_link_libraries(kwin_wayland ${Libcap_LIBRARIES}) +endif() install(TARGETS kwin_wayland ${INSTALL_TARGETS_DEFAULT_ARGS} ) +if (HAVE_LIBCAP) + install( + CODE "execute_process( + COMMAND + ${SETCAP_EXECUTABLE} + CAP_SYS_NICE=+ep + ${CMAKE_INSTALL_FULL_BINDIR}/kwin_wayland)" + ) +endif() add_subdirectory(platformsupport) add_subdirectory(plugins) diff --git a/cmake/modules/FindLibcap.cmake b/cmake/modules/FindLibcap.cmake new file mode 100644 index 0000000000..4a32446203 --- /dev/null +++ b/cmake/modules/FindLibcap.cmake @@ -0,0 +1,59 @@ +# Try to find the setcap binary and cap libraries +# +# This will define: +# +# Libcap_FOUND - system has the cap library and setcap binary +# Libcap_LIBRARIES - cap libraries to link against +# SETCAP_EXECUTABLE - path of the setcap binary +# In addition, the following targets are defined: +# +# Libcap::SetCapabilities +# + + +# Copyright (c) 2014, Hrvoje Senjan, +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +find_program(SETCAP_EXECUTABLE NAMES setcap DOC "The setcap executable") + +find_library(Libcap_LIBRARIES NAMES cap DOC "The cap (capabilities) library") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libcap FOUND_VAR Libcap_FOUND + REQUIRED_VARS SETCAP_EXECUTABLE Libcap_LIBRARIES) + +if(Libcap_FOUND AND NOT TARGET Libcap::SetCapabilities) + add_executable(Libcap::SetCapabilities IMPORTED) + set_target_properties(Libcap::SetCapabilities PROPERTIES + IMPORTED_LOCATION "${SETCAP_EXECUTABLE}" + ) +endif() + +mark_as_advanced(SETCAP_EXECUTABLE Libcap_LIBRARIES) + +include(FeatureSummary) +set_package_properties(Libcap PROPERTIES + URL https://sites.google.com/site/fullycapable/ + DESCRIPTION "Capabilities are a measure to limit the omnipotence of the superuser.") diff --git a/config-kwin.h.cmake b/config-kwin.h.cmake index 7b04cb79b9..1566d649f6 100644 --- a/config-kwin.h.cmake +++ b/config-kwin.h.cmake @@ -24,6 +24,8 @@ #cmakedefine01 HAVE_SYS_SYSMACROS_H #cmakedefine01 HAVE_BREEZE_DECO #cmakedefine01 HAVE_UDEV +#cmakedefine01 HAVE_LIBCAP +#cmakedefine01 HAVE_SCHED_RESET_ON_FORK #if HAVE_BREEZE_DECO #define BREEZE_KDECORATION_PLUGIN_ID "${BREEZE_KDECORATION_PLUGIN_ID}" #endif diff --git a/main_wayland.cpp b/main_wayland.cpp index 0e69d06914..c1915fc9ca 100644 --- a/main_wayland.cpp +++ b/main_wayland.cpp @@ -63,6 +63,12 @@ along with this program. If not, see . #include #endif +#if HAVE_LIBCAP +#include +#endif + +#include + #include #include @@ -438,6 +444,37 @@ static void unsetDumpable(int sig) return; } +void gainRealTime() +{ +#if HAVE_SCHED_RESET_ON_FORK + const int minPriority = sched_get_priority_min(SCHED_RR); + struct sched_param sp; + sp.sched_priority = minPriority; + sched_setscheduler(0, SCHED_RR | SCHED_RESET_ON_FORK, &sp); +#endif +} + +void dropNiceCapability() +{ +#if HAVE_LIBCAP + cap_t caps = cap_get_proc(); + if (!caps) { + return; + } + cap_value_t capList[] = { CAP_SYS_NICE }; + if (cap_set_flag(caps, CAP_PERMITTED, 1, capList, CAP_CLEAR) == -1) { + cap_free(caps); + return; + } + if (cap_set_flag(caps, CAP_EFFECTIVE, 1, capList, CAP_CLEAR) == -1) { + cap_free(caps); + return; + } + cap_set_proc(caps); + cap_free(caps); +#endif +} + } // namespace int main(int argc, char * argv[]) @@ -445,6 +482,8 @@ int main(int argc, char * argv[]) KWin::disablePtrace(); KWin::Application::setupMalloc(); KWin::Application::setupLocalizedString(); + KWin::gainRealTime(); + KWin::dropNiceCapability(); if (signal(SIGTERM, KWin::sighandler) == SIG_IGN) signal(SIGTERM, SIG_IGN);