this repo has no description
at trunk 190 lines 6.3 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "under-signal-module.h" 3 4#include <unistd.h> 5 6#include <cerrno> 7#include <csignal> 8 9#include "builtins.h" 10#include "int-builtins.h" 11#include "module-builtins.h" 12#include "modules.h" 13#include "os.h" 14#include "runtime.h" 15#include "set-builtins.h" 16#include "symbols.h" 17#include "type-builtins.h" 18 19namespace py { 20 21void FUNC(_signal, __init_module__)(Thread* thread, const Module& module, 22 View<byte> bytecode) { 23 HandleScope scope(thread); 24 Object nsig(&scope, SmallInt::fromWord(OS::kNumSignals)); 25 moduleAtPutById(thread, module, ID(NSIG), nsig); 26 27 Object sig_dfl(&scope, kDefaultHandler); 28 moduleAtPutById(thread, module, ID(SIG_DFL), sig_dfl); 29 30 Object sig_ign(&scope, kIgnoreHandler); 31 moduleAtPutById(thread, module, ID(SIG_IGN), sig_ign); 32 33 Object signum(&scope, NoneType::object()); 34 for (const OS::Signal* signal = OS::kStandardSignals; signal->name != nullptr; 35 signal++) { 36 signum = SmallInt::fromWord(signal->signum); 37 moduleAtPutByCStr(thread, module, signal->name, signum); 38 } 39 for (const OS::Signal* signal = OS::kPlatformSignals; signal->name != nullptr; 40 signal++) { 41 signum = SmallInt::fromWord(signal->signum); 42 moduleAtPutByCStr(thread, module, signal->name, signum); 43 } 44 45 executeFrozenModule(thread, module, bytecode); 46 47 thread->runtime()->initializeSignals(thread, module); 48} 49 50void handleSignal(int signum) { 51 Thread* thread = Thread::current(); 52 int saved_errno = errno; 53 thread->runtime()->setPendingSignal(thread, signum); 54 errno = saved_errno; 55} 56 57RawObject FUNC(_signal, default_int_handler)(Thread* thread, Arguments) { 58 return thread->raise(LayoutId::kKeyboardInterrupt, NoneType::object()); 59} 60 61RawObject FUNC(_signal, getsignal)(Thread* thread, Arguments args) { 62 HandleScope scope(thread); 63 Runtime* runtime = thread->runtime(); 64 Object obj(&scope, args.get(0)); 65 if (!runtime->isInstanceOfInt(*obj)) { 66 return thread->raiseRequiresType(obj, ID(int)); 67 } 68 word signum = intUnderlying(*obj).asWord(); 69 if (signum < 1 || signum >= OS::kNumSignals) { 70 return thread->raiseWithFmt(LayoutId::kValueError, 71 "signal number out of range"); 72 } 73 return runtime->signalCallback(signum); 74} 75 76RawObject FUNC(_signal, signal)(Thread* thread, Arguments args) { 77 HandleScope scope(thread); 78 Runtime* runtime = thread->runtime(); 79 Object obj(&scope, args.get(0)); 80 if (!runtime->isInstanceOfInt(*obj)) { 81 return thread->raiseRequiresType(obj, ID(int)); 82 } 83 84 if (!thread->isMainThread()) { 85 return thread->raiseWithFmt(LayoutId::kValueError, 86 "signal only works in main thread"); 87 } 88 89 word signum = intUnderlying(*obj).asWord(); 90 if (signum < 1 || signum >= OS::kNumSignals) { 91 return thread->raiseWithFmt(LayoutId::kValueError, 92 "signal number out of range"); 93 } 94 95 Object callback(&scope, args.get(1)); 96 SignalHandler handler; 97 if (callback == kIgnoreHandler) { 98 handler = SIG_IGN; 99 } else if (callback == kDefaultHandler) { 100 handler = SIG_DFL; 101 } else { 102 Type type(&scope, runtime->typeOf(*callback)); 103 if (typeLookupInMroById(thread, *type, ID(__call__)).isErrorNotFound()) { 104 return thread->raiseWithFmt(LayoutId::kTypeError, 105 "signal handler must be signal.SIG_IGN, " 106 "signal.SIG_DFL, or a callable object"); 107 } 108 handler = handleSignal; 109 } 110 111 Object err(&scope, runtime->handlePendingSignals(thread)); 112 if (err.isErrorException()) { 113 return *err; 114 } 115 if (OS::setSignalHandler(signum, handler) == SIG_ERR) { 116 return thread->raise(LayoutId::kOSError, NoneType::object()); 117 } 118 return runtime->setSignalCallback(signum, callback); 119} 120 121RawObject FUNC(_signal, alarm)(Thread* thread, Arguments args) { 122 HandleScope scope(thread); 123 Runtime* runtime = thread->runtime(); 124 Object obj(&scope, args.get(0)); 125 if (!runtime->isInstanceOfInt(*obj)) { 126 return thread->raiseRequiresType(obj, ID(int)); 127 } 128 obj = intUnderlying(*obj); 129 if (obj.isLargeInt()) { 130 return thread->raiseWithFmt(LayoutId::kOverflowError, 131 "Python int too large to convert to C long"); 132 } 133 word seconds_remaining = ::alarm(Int::cast(*obj).asWord()); 134 return SmallInt::fromWord(seconds_remaining); 135} 136 137RawObject FUNC(_signal, valid_signals)(Thread* thread, Arguments) { 138 HandleScope scope(thread); 139 Runtime* runtime = thread->runtime(); 140 sigset_t mask; 141 if (sigemptyset(&mask) || sigfillset(&mask)) { 142 return thread->raiseWithFmt(LayoutId::kOSError, 143 "Error while retreiving valid signals."); 144 } 145 Set set(&scope, runtime->newSet()); 146 Object value(&scope, NoneType::object()); 147 for (word signal = 1; signal < NSIG; signal++) { 148 if (sigismember(&mask, signal) != 1) { 149 continue; 150 } 151 value = runtime->newInt(signal); 152 word hash = intHash(*value); 153 setAdd(thread, set, value, hash); 154 } 155 return *set; 156} 157 158RawObject FUNC(_signal, siginterrupt)(Thread* thread, Arguments args) { 159 HandleScope scope(thread); 160 Runtime* runtime = thread->runtime(); 161 Object signalnum_obj(&scope, args.get(0)); 162 if (!runtime->isInstanceOfInt(*signalnum_obj)) { 163 return thread->raiseWithFmt(LayoutId::kTypeError, 164 "`signalnum` must be an integer (got type %T)", 165 &signalnum_obj); 166 } 167 word signalnum = intUnderlying(*signalnum_obj).asWordSaturated(); 168 Object flag_obj(&scope, args.get(1)); 169 if (!runtime->isInstanceOfInt(*flag_obj)) { 170 return thread->raiseWithFmt(LayoutId::kTypeError, 171 "`flag` must be an integer (got type %T)", 172 &flag_obj); 173 } 174 word flag = intUnderlying(*flag_obj).asWordSaturated(); 175 176 if (signalnum < 1 || signalnum >= NSIG) { 177 return thread->raiseWithFmt(LayoutId::kValueError, 178 "signal number out of range"); 179 } 180#pragma GCC diagnostic push 181#pragma GCC diagnostic ignored "-Wdeprecated-declarations" 182 word result = ::siginterrupt(signalnum, flag); 183#pragma GCC diagnostic pop 184 if (result < 0) { 185 return thread->raiseOSErrorFromErrno(-result); 186 } 187 return NoneType::object(); 188} 189 190} // namespace py