1 #pragma once
2 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
3 #include <cstdio>
4 #include <cstdlib>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include <type_traits>
8 #include <unistd.h>
9 #include <utility>
10 // copied from cppreference as possible implementation
11 namespace detail {
INVOKE(F && f,Args &&...args)12 template <class F, class... Args> inline auto INVOKE(F &&f, Args &&... args) -> decltype(std::forward<F>(f)(std::forward<Args>(args)...))
13 {
14     return std::forward<F>(f)(std::forward<Args>(args)...);
15 }
16 
INVOKE(T Base::* pmd,Derived && ref)17 template <class Base, class T, class Derived> inline auto INVOKE(T Base::*pmd, Derived &&ref) -> decltype(std::forward<Derived>(ref).*pmd)
18 {
19     return std::forward<Derived>(ref).*pmd;
20 }
21 
INVOKE(PMD pmd,Pointer && ptr)22 template <class PMD, class Pointer> inline auto INVOKE(PMD pmd, Pointer &&ptr) -> decltype((*std::forward<Pointer>(ptr)).*pmd)
23 {
24     return (*std::forward<Pointer>(ptr)).*pmd;
25 }
26 
27 template <class Base, class T, class Derived, class... Args>
INVOKE(T Base::* pmf,Derived && ref,Args &&...args)28 inline auto INVOKE(T Base::*pmf, Derived &&ref, Args &&... args) -> decltype((std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...))
29 {
30     return (std::forward<Derived>(ref).*pmf)(std::forward<Args>(args)...);
31 }
32 
33 template <class PMF, class Pointer, class... Args>
INVOKE(PMF pmf,Pointer && ptr,Args &&...args)34 inline auto INVOKE(PMF pmf, Pointer &&ptr, Args &&... args) -> decltype(((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...))
35 {
36     return ((*std::forward<Pointer>(ptr)).*pmf)(std::forward<Args>(args)...);
37 }
38 } // namespace detail
39 
40 namespace util {
invoke(F && f,ArgTypes &&...args)41 template <class F, class... ArgTypes> decltype(auto) invoke(F &&f, ArgTypes &&... args)
42 {
43     return detail::INVOKE(std::forward<F>(f), std::forward<ArgTypes>(args)...);
44 }
45 } // namespace util
46 
47 void Disable_Console_Output();
48 
ABORTS(F && f,Args &&...args)49 template <class F, class... Args> bool ABORTS(F &&f, Args &&... args)
50 {
51     // pipe
52     int fd[2];
53     pipe(fd);
54 
55     // spawn a new process
56     auto child_pid = fork();
57     bool aborted = false;
58 
59     // if the fork succeeded
60     if (child_pid >= 0) {
61 
62         // if we are in the child process
63         if (child_pid == 0) {
64             close(fd[0]);
65 
66             // call the function that we expect to abort
67             Disable_Console_Output();
68             util::invoke(std::forward<F>(f), std::forward<Args>(args)...);
69 
70             char succ[] = "1";
71             write(fd[1], succ, 2);
72 
73             // if the function didn't abort, we'll exit cleanly
74             std::exit(EXIT_SUCCESS);
75         } else {
76             close(fd[1]);
77             char buff[128];
78             int n = read(fd[0], buff, 127);
79             aborted = n == 0;
80         }
81     }
82 
83     return aborted;
84 }
85 #else
ABORTS(F &&,Args &&...)86 template <class F, class... Args> bool ABORTS(F &&, Args &&...)
87 {
88     return true;
89 }
90 #endif
91