[videodb] remove unused seasons table from episode_view
[xbmc.git] / xbmc / platform / posix / utils / SharedMemory.cpp
blob6c1318e936e0f9716b053961ee22e82b24cf7910
1 /*
2 * Copyright (C) 2017-2018 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
9 #include "SharedMemory.h"
11 #include <fcntl.h>
12 #include <sys/mman.h>
13 #include <unistd.h>
15 #if defined(HAVE_LINUX_MEMFD)
16 #include <linux/memfd.h>
17 #include <sys/syscall.h>
18 #endif
20 #include <cerrno>
21 #include <cstdlib>
22 #include <system_error>
24 #include "utils/log.h"
26 using namespace KODI::UTILS::POSIX;
28 CSharedMemory::CSharedMemory(std::size_t size)
29 : m_size{size}, m_fd{Open()}, m_mmap(nullptr, m_size, PROT_READ | PROT_WRITE, MAP_SHARED, m_fd, 0)
33 CFileHandle CSharedMemory::Open()
35 CFileHandle fd;
36 try
38 fd = OpenMemfd();
40 catch (std::system_error const& error)
42 if (error.code() == std::errc::function_not_supported)
44 CLog::Log(LOGDEBUG, "Kernel does not support memfd, falling back to plain shm");
45 fd = OpenShm();
47 else
49 throw;
53 if (ftruncate(fd, m_size) < 0)
55 throw std::system_error(errno, std::generic_category(), "ftruncate");
58 return fd;
61 CFileHandle CSharedMemory::OpenMemfd()
63 #if defined(SYS_memfd_create) && defined(HAVE_LINUX_MEMFD)
64 // This is specific to Linux >= 3.17, but preferred over shm_create if available
65 // because it is race-free
66 int fd = syscall(SYS_memfd_create, "kodi", MFD_CLOEXEC);
67 if (fd < 0)
69 throw std::system_error(errno, std::generic_category(), "memfd_create");
72 return CFileHandle(fd);
73 #else
74 throw std::system_error(std::make_error_code(std::errc::function_not_supported), "memfd_create");
75 #endif
78 CFileHandle CSharedMemory::OpenShm()
80 char* xdgRuntimeDir = std::getenv("XDG_RUNTIME_DIR");
81 if (!xdgRuntimeDir)
83 throw std::runtime_error("XDG_RUNTIME_DIR environment variable must be set");
86 std::string tmpFilename(xdgRuntimeDir);
87 tmpFilename.append("/kodi-shared-XXXXXX");
89 int rawFd;
90 #if defined(HAVE_MKOSTEMP)
91 // Opening the file with O_CLOEXEC is preferred since it avoids races where
92 // other threads might exec() before setting the CLOEXEC flag
93 rawFd = mkostemp(&tmpFilename[0], O_CLOEXEC);
94 #else
95 rawFd = mkstemp(&tmpFilename[0]);
96 #endif
98 if (rawFd < 0)
100 throw std::system_error(errno, std::generic_category(), "mkstemp");
102 CFileHandle fd(rawFd);
104 int flags = fcntl(fd, F_GETFD);
105 if (flags < 0)
107 throw std::system_error(errno, std::generic_category(), "fcntl F_GETFD");
109 // Set FD_CLOEXEC if unset
110 if (!(flags & FD_CLOEXEC) && fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
112 throw std::system_error(errno, std::generic_category(), "fcntl F_SETFD FD_CLOEXEC");
115 unlink(tmpFilename.c_str());
117 return fd;