File indexing completed on 2025-04-20 04:29:50
0001 /* 0002 SPDX-FileCopyrightText: 2019 Nicolas Carion <french.ebook.lover@gmail.com> 0003 SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 */ 0005 #pragma once 0006 0007 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) 0008 #include <cstdio> 0009 #include <cstdlib> 0010 #include <sys/types.h> 0011 #include <sys/wait.h> 0012 #include <type_traits> 0013 #include <unistd.h> 0014 #include <utility> 0015 // copied from cppreference as possible implementation 0016 namespace detail { 0017 template <class F, class... Args> inline auto INVOKE(F &&f, Args &&... args) -> decltype(std::forward<F>(f)(std::forward<Args>(args)...)) 0018 { 0019 return std::forward<F>(f)(std::forward<Args>(args)...); 0020 } 0021 0022 template <class Base, class T, class Derived> inline auto INVOKE(T Base::*pmd, Derived &&ref) -> decltype(std::forward<Derived>(ref).*pmd) 0023 { 0024 return std::forward<Derived>(ref).*pmd; 0025 } 0026 0027 template <class PMD, class Pointer> inline auto INVOKE(PMD pmd, Pointer &&ptr) -> decltype((*std::forward<Pointer>(ptr)).*pmd) 0028 { 0029 return (*std::forward<Pointer>(ptr)).*pmd; 0030 } 0031 0032 template <class Base, class T, class Derived, class... Args> 0033 inline auto INVOKE(T Base::*pmf, Derived &&ref, Args &&... args) -> decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...)) 0034 { 0035 return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...); 0036 } 0037 0038 template <class PMF, class Pointer, class... Args> 0039 inline auto INVOKE(PMF pmf, Pointer &&ptr, Args &&... args) -> decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...)) 0040 { 0041 return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...); 0042 } 0043 } // namespace detail 0044 0045 namespace util { 0046 template <class F, class... ArgTypes> decltype(auto) invoke(F &&f, ArgTypes &&... args) 0047 { 0048 return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...); 0049 } 0050 } // namespace util 0051 0052 void Disable_Console_Output(); 0053 0054 template <class F, class... Args> bool ABORTS(F &&f, Args &&... args) 0055 { 0056 // pipe 0057 int fd[2]; 0058 pipe(fd); 0059 0060 // spawn a new process 0061 auto child_pid = fork(); 0062 bool aborted = false; 0063 0064 // if the fork succeeded 0065 if (child_pid >= 0) { 0066 0067 // if we are in the child process 0068 if (child_pid == 0) { 0069 close(fd[0]); 0070 0071 // call the function that we expect to abort 0072 Disable_Console_Output(); 0073 util::invoke(std::forward<F>(f), std::forward<Args>(args)...); 0074 0075 char succ[] = "1"; 0076 write(fd[1], succ, 2); 0077 0078 // if the function didn't abort, we'll exit cleanly 0079 std::exit(EXIT_SUCCESS); 0080 } else { 0081 close(fd[1]); 0082 char buff[128]; 0083 int n = read(fd[0], buff, 127); 0084 aborted = n == 0; 0085 } 0086 } 0087 0088 return aborted; 0089 } 0090 #else 0091 template <class F, class... Args> bool ABORTS(F &&, Args &&...) 0092 { 0093 return true; 0094 } 0095 #endif