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