this repo has no description
at trunk 106 lines 3.7 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "builtins.h" 3#include "exception-builtins.h" 4#include "frame.h" 5#include "globals.h" 6#include "handles.h" 7#include "modules.h" 8#include "os.h" 9#include "runtime.h" 10#include "sys-module.h" 11#include "thread.h" 12 13namespace py { 14 15RawObject FUNC(_thread, get_ident)(Thread* thread, Arguments) { 16 return thread->runtime()->newIntFromCPtr(thread); 17} 18 19static void* threadBegin(void* arg) { 20 Thread* thread = reinterpret_cast<Thread*>(arg); 21 thread->begin(); 22 { 23 HandleScope scope(thread); 24 Object func(&scope, thread->stackPeek(2)); 25 Object result( 26 &scope, Interpreter::callEx(thread, CallFunctionExFlag::VAR_KEYWORDS)); 27 if (result.isErrorException()) { 28 if (thread->pendingExceptionMatches(LayoutId::kSystemExit)) { 29 thread->clearPendingException(); 30 } else { 31 // TODO(T89490118): call sys.unraisablehook instead 32 Object exc(&scope, thread->pendingExceptionType()); 33 Object val(&scope, thread->pendingExceptionValue()); 34 Object tb(&scope, thread->pendingExceptionTraceback()); 35 thread->clearPendingException(); 36 37 Object func_str(&scope, 38 thread->invokeFunction1(ID(builtins), ID(str), func)); 39 if (func_str.isErrorException()) { 40 writeStderr(thread, "Exception ignored in thread started by: \n"); 41 } else { 42 Str str(&scope, strUnderlying(*func_str)); 43 word length = str.length(); 44 unique_c_ptr<byte[]> buf( 45 reinterpret_cast<byte*>(std::malloc(length + 1))); 46 str.copyTo(buf.get(), length); 47 buf[length] = '\0'; 48 writeStderr(thread, "Exception ignored in thread started by: %s\n", 49 buf.get()); 50 } 51 52 thread->setPendingExceptionType(*exc); 53 thread->setPendingExceptionValue(*val); 54 thread->setPendingExceptionTraceback(*tb); 55 printPendingException(thread); 56 } 57 } 58 } 59 thread->runtime()->deleteThread(thread); 60 return nullptr; 61} 62 63static RawObject startNewThread(Thread* thread, Arguments args) { 64 HandleScope scope(thread); 65 Runtime* runtime = thread->runtime(); 66 // TODO(T66337218): remove this guard once threading is safe 67 if (runtime->lookupNameInModule(thread, ID(_thread), ID(_enable_threads)) 68 .isErrorNotFound()) { 69 UNIMPLEMENTED( 70 "PyRO runtime is not thread-safe. " 71 "Set `_thread._enable_threads = True` to bypass."); 72 } 73 Object func(&scope, args.get(0)); 74 if (!runtime->isCallable(thread, func)) { 75 return thread->raiseWithFmt(LayoutId::kTypeError, 76 "first arg must be callable"); 77 } 78 Object args_obj(&scope, args.get(1)); 79 if (!runtime->isInstanceOfTuple(*args_obj)) { 80 return thread->raiseWithFmt(LayoutId::kTypeError, 81 "2nd arg must be a tuple"); 82 } 83 Object kwargs(&scope, args.get(2)); 84 if (kwargs.isUnbound()) { 85 kwargs = runtime->newDict(); 86 } else if (!runtime->isInstanceOfDict(*kwargs)) { 87 return thread->raiseWithFmt(LayoutId::kTypeError, 88 "optional 3rd arg must be a dictionary"); 89 } 90 Thread* new_thread = runtime->newThread(); 91 new_thread->stackPush(*func); 92 new_thread->stackPush(*args_obj); 93 new_thread->stackPush(*kwargs); 94 OS::createThread(threadBegin, new_thread); 95 return runtime->newIntFromCPtr(new_thread); 96} 97 98RawObject FUNC(_thread, start_new)(Thread* thread, Arguments args) { 99 return startNewThread(thread, args); 100} 101 102RawObject FUNC(_thread, start_new_thread)(Thread* thread, Arguments args) { 103 return startNewThread(thread, args); 104} 105 106} // namespace py