this repo has no description
at trunk 383 lines 14 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "sys-module.h" 3 4#include <unistd.h> 5 6#include <cerrno> 7#include <cstdio> 8#include <cstring> 9 10#include "cpython-types.h" 11 12#include "builtins-module.h" 13#include "builtins.h" 14#include "bytes-builtins.h" 15#include "capi.h" 16#include "dict-builtins.h" 17#include "exception-builtins.h" 18#include "file.h" 19#include "frame.h" 20#include "frozen-modules.h" 21#include "globals.h" 22#include "handles.h" 23#include "int-builtins.h" 24#include "module-builtins.h" 25#include "modules.h" 26#include "objects.h" 27#include "os.h" 28#include "runtime.h" 29#include "str-builtins.h" 30#include "thread.h" 31#include "version.h" 32 33namespace py { 34 35void FUNC(sys, __init_module__)(Thread* thread, const Module& module, 36 View<byte> bytecode) { 37 HandleScope scope(thread); 38 Runtime* runtime = thread->runtime(); 39 Object modules(&scope, runtime->modules()); 40 moduleAtPutById(thread, module, ID(modules), modules); 41 42 // Fill in sys... 43 Object platform(&scope, runtime->newStrFromCStr(OS::name())); 44 moduleAtPutById(thread, module, ID(platform), platform); 45 46 Object stderr_fd_val(&scope, SmallInt::fromWord(File::kStderr)); 47 moduleAtPutById(thread, module, ID(_stderr_fd), stderr_fd_val); 48 Object stdin_fd_val(&scope, SmallInt::fromWord(File::kStdin)); 49 moduleAtPutById(thread, module, ID(_stdin_fd), stdin_fd_val); 50 Object stdout_fd_val(&scope, SmallInt::fromWord(File::kStdout)); 51 moduleAtPutById(thread, module, ID(_stdout_fd), stdout_fd_val); 52 53 Object byteorder( 54 &scope, 55 SmallStr::fromCStr(endian::native == endian::little ? "little" : "big")); 56 moduleAtPutById(thread, module, ID(byteorder), byteorder); 57 58 // maxsize is defined as the largest supported length of containers which 59 // would be `SmallInt::kMaxValue`. However in practice it is used to 60 // determine the size of a machine word which is kMaxWord. 61 Object maxsize(&scope, runtime->newInt(kMaxWord)); 62 moduleAtPutById(thread, module, ID(maxsize), maxsize); 63 64 // Count the number of builtin modules and create a tuple 65 uword num_extension_modules = 0; 66 while (PyImport_Inittab[num_extension_modules].name != nullptr) { 67 num_extension_modules++; 68 } 69 word num_builtin_modules = kNumFrozenModules + num_extension_modules; 70 MutableTuple builtin_module_names( 71 &scope, runtime->newMutableTuple(num_builtin_modules)); 72 for (word i = 0; i < kNumFrozenModules; i++) { 73 builtin_module_names.atPut( 74 i, Runtime::internStrFromCStr(thread, kFrozenModules[i].name)); 75 } 76 for (int i = 0; PyImport_Inittab[i].name != nullptr; i++) { 77 builtin_module_names.atPut( 78 kNumFrozenModules + i, 79 Runtime::internStrFromCStr(thread, PyImport_Inittab[i].name)); 80 } 81 Tuple builtin_module_names_tuple(&scope, 82 builtin_module_names.becomeImmutable()); 83 moduleAtPutById(thread, module, ID(builtin_module_names), 84 builtin_module_names_tuple); 85 86 // Fill in version-related fields. 87 Int hexversion(&scope, SmallInt::fromWord(kVersionHex)); 88 moduleAtPutById(thread, module, ID(hexversion), hexversion); 89 Str version(&scope, runtime->newStrFromCStr(kVersionInfo)); 90 moduleAtPutById(thread, module, ID(version), version); 91 Object release_level(&scope, runtime->newStrFromCStr(kReleaseLevel)); 92 moduleAtPutById(thread, module, ID(_version_releaselevel), release_level); 93 94 Object buffered_stdio(&scope, Bool::fromBool(runtime->useBufferedStdio())); 95 moduleAtPutById(thread, module, ID(_use_buffered_stdio), buffered_stdio); 96 97 executeFrozenModule(thread, module, bytecode); 98 99 // Fill in hash_info. 100 Object hash_width(&scope, SmallInt::fromWord(SmallInt::kBits)); 101 Object hash_modulus(&scope, SmallInt::fromWord(kArithmeticHashModulus)); 102 Object hash_inf(&scope, SmallInt::fromWord(kHashInf)); 103 Object hash_nan(&scope, SmallInt::fromWord(kHashNan)); 104 Object hash_imag(&scope, SmallInt::fromWord(kHashImag)); 105 Object hash_algorithm(&scope, runtime->symbols()->at(ID(siphash24))); 106 Object hash_bits(&scope, SmallInt::fromWord(64)); 107 Object hash_seed_bits(&scope, SmallInt::fromWord(128)); 108 Object hash_cutoff(&scope, SmallInt::fromWord(SmallStr::kMaxLength)); 109 Tuple hash_info_data(&scope, runtime->newTupleWithN( 110 9, &hash_width, &hash_modulus, &hash_inf, 111 &hash_nan, &hash_imag, &hash_algorithm, 112 &hash_bits, &hash_seed_bits, &hash_cutoff)); 113 Object hash_info( 114 &scope, thread->invokeFunction1(ID(sys), ID(_HashInfo), hash_info_data)); 115 moduleAtPutById(thread, module, ID(hash_info), hash_info); 116 117 runtime->cacheSysInstances(thread, module); 118} 119 120int flushStdFiles() { 121 Thread* thread = Thread::current(); 122 HandleScope scope(thread); 123 int return_value = 0; 124 125 // PyErr_Fetch 126 Object exc(&scope, thread->pendingExceptionType()); 127 Object val(&scope, thread->pendingExceptionValue()); 128 Object tb(&scope, thread->pendingExceptionTraceback()); 129 thread->clearPendingException(); 130 131 Runtime* runtime = thread->runtime(); 132 Module sys(&scope, runtime->findModuleById(ID(sys))); 133 Object stdout_obj(&scope, moduleAtById(thread, sys, ID(stdout))); 134 if (!stdout_obj.isErrorNotFound()) { 135 if (thread->invokeMethod1(stdout_obj, ID(flush)).isErrorException()) { 136 thread->clearPendingException(); 137 return_value = -1; 138 } 139 } 140 Object stderr_obj(&scope, moduleAtById(thread, sys, ID(stderr))); 141 if (!stderr_obj.isErrorNotFound()) { 142 if (thread->invokeMethod1(stderr_obj, ID(flush)).isErrorException()) { 143 thread->clearPendingException(); 144 return_value = -1; 145 } 146 } 147 148 // PyErr_Restore 149 thread->setPendingExceptionType(*exc); 150 thread->setPendingExceptionValue(*val); 151 thread->setPendingExceptionTraceback(*tb); 152 return return_value; 153} 154 155void initializeRuntimePaths(Thread* thread) { 156 HandleScope scope(thread); 157 Object result(&scope, thread->invokeFunction0(ID(sys), ID(_calculate_path))); 158 if (result.isError()) { 159 thread->clearPendingException(); 160 thread->raiseBadInternalCall(); 161 return; 162 } 163 CHECK(result.isTuple(), "sys._calculate_path must return tuple"); 164 Tuple paths(&scope, *result); 165 166 Str prefix(&scope, paths.at(0)); 167 word prefix_codepoints = prefix.codePointLength(); 168 std::unique_ptr<wchar_t[]> prefix_wstr(new wchar_t[prefix_codepoints + 1]); 169 strCopyToWCStr(prefix_wstr.get(), prefix_codepoints + 1, prefix); 170 Runtime::setPrefix(prefix_wstr.get()); 171 172 Str exec_prefix(&scope, paths.at(1)); 173 word exec_prefix_codepoints = exec_prefix.codePointLength(); 174 std::unique_ptr<wchar_t[]> exec_prefix_wstr( 175 new wchar_t[exec_prefix_codepoints + 1]); 176 strCopyToWCStr(exec_prefix_wstr.get(), exec_prefix_codepoints + 1, 177 exec_prefix); 178 Runtime::setExecPrefix(exec_prefix_wstr.get()); 179 180 Str module_search_path(&scope, paths.at(2)); 181 word module_search_path_codepoints = module_search_path.codePointLength(); 182 std::unique_ptr<wchar_t[]> module_search_path_wstr( 183 new wchar_t[module_search_path_codepoints + 1]); 184 strCopyToWCStr(module_search_path_wstr.get(), 185 module_search_path_codepoints + 1, module_search_path); 186 Runtime::setModuleSearchPath(module_search_path_wstr.get()); 187} 188 189RawObject initializeSys(Thread* thread, const Str& executable, 190 const List& python_path, const Tuple& flags_data, 191 const List& warnoptions, 192 bool extend_python_path_with_stdlib) { 193 HandleScope scope(thread); 194 Object extend_python_path_with_stdlib_obj( 195 &scope, Bool::fromBool(extend_python_path_with_stdlib)); 196 return thread->invokeFunction5(ID(sys), ID(_init), executable, python_path, 197 flags_data, warnoptions, 198 extend_python_path_with_stdlib_obj); 199} 200 201void setPycachePrefix(Thread* thread, const Object& pycache_prefix) { 202 HandleScope scope(thread); 203 Runtime* runtime = thread->runtime(); 204 Module module(&scope, runtime->findModuleById(ID(sys))); 205 moduleAtPutById(thread, module, ID(pycache_prefix), pycache_prefix); 206} 207 208static void writeImpl(Thread* thread, const Object& file, FILE* fallback_fp, 209 const char* format, va_list va) { 210 HandleScope scope(thread); 211 Object type(&scope, thread->pendingExceptionType()); 212 Object value(&scope, thread->pendingExceptionValue()); 213 Object tb(&scope, thread->pendingExceptionTraceback()); 214 thread->clearPendingException(); 215 216 static const char truncated[] = "... truncated"; 217 static constexpr int message_size = 1001; 218 char buffer[message_size + sizeof(truncated) - 1]; 219 int written = std::vsnprintf(buffer, message_size, format, va); 220 CHECK(written >= 0, "vsnprintf failed"); 221 if (written >= message_size) { 222 std::memcpy(&buffer[message_size - 1], truncated, sizeof(truncated)); 223 written = message_size + sizeof(truncated) - 2; 224 } 225 Str str(&scope, thread->runtime()->newStrWithAll( 226 View<byte>(reinterpret_cast<byte*>(buffer), written))); 227 if (file.isNoneType() || 228 thread->invokeMethod2(file, ID(write), str).isError()) { 229 fwrite(buffer, 1, written, fallback_fp); 230 } 231 232 thread->clearPendingException(); 233 thread->setPendingExceptionType(*type); 234 thread->setPendingExceptionValue(*value); 235 thread->setPendingExceptionTraceback(*tb); 236} 237 238void writeStdout(Thread* thread, const char* format, ...) { 239 va_list va; 240 va_start(va, format); 241 writeStdoutV(thread, format, va); 242 va_end(va); 243} 244 245void writeStdoutV(Thread* thread, const char* format, va_list va) { 246 HandleScope scope(thread); 247 ValueCell sys_stdout_cell(&scope, thread->runtime()->sysStdout()); 248 Object sys_stdout(&scope, NoneType::object()); 249 if (!sys_stdout_cell.isUnbound()) { 250 sys_stdout = sys_stdout_cell.value(); 251 } 252 writeImpl(thread, sys_stdout, stdout, format, va); 253} 254 255void writeStderr(Thread* thread, const char* format, ...) { 256 va_list va; 257 va_start(va, format); 258 writeStderrV(thread, format, va); 259 va_end(va); 260} 261 262void writeStderrV(Thread* thread, const char* format, va_list va) { 263 HandleScope scope(thread); 264 ValueCell sys_stderr_cell(&scope, thread->runtime()->sysStderr()); 265 Object sys_stderr(&scope, NoneType::object()); 266 if (!sys_stderr_cell.isUnbound()) { 267 sys_stderr = sys_stderr_cell.value(); 268 } 269 writeImpl(thread, sys_stderr, stderr, format, va); 270} 271 272RawObject FUNC(sys, _getframe)(Thread* thread, Arguments args) { 273 HandleScope scope(thread); 274 Runtime* runtime = thread->runtime(); 275 Object depth_obj(&scope, args.get(0)); 276 if (!runtime->isInstanceOfInt(*depth_obj)) { 277 return thread->raiseRequiresType(depth_obj, ID(int)); 278 } 279 word depth = intUnderlying(*depth_obj).asWordSaturated(); 280 if (depth < 0) { 281 depth = 0; 282 } 283 // Increment the requested depth to skip the frame for sys._getframe itself. 284 // TODO(T64005113): This should be deleted. 285 depth++; 286 Object result(&scope, thread->heapFrameAtDepth(depth)); 287 if (result.isNoneType()) { 288 return thread->raiseWithFmt(LayoutId::kValueError, 289 "call stack is not deep enough"); 290 } 291 return *result; 292} 293 294RawObject FUNC(sys, _program_name)(Thread* thread, Arguments) { 295 return newStrFromWideChar(thread, Runtime::programName()); 296} 297 298RawObject FUNC(sys, excepthook)(Thread* thread, Arguments args) { 299 HandleScope scope(thread); 300 // type argument is ignored 301 Object value(&scope, args.get(1)); 302 Object tb(&scope, args.get(2)); 303 return displayException(thread, value, tb); 304} 305 306RawObject FUNC(sys, exc_info)(Thread* thread, Arguments) { 307 HandleScope scope(thread); 308 Object caught_exc_state_obj(&scope, thread->topmostCaughtExceptionState()); 309 if (caught_exc_state_obj.isNoneType()) { 310 Object type(&scope, NoneType::object()); 311 Object value(&scope, NoneType::object()); 312 Object traceback(&scope, NoneType::object()); 313 return thread->runtime()->newTupleWith3(type, value, traceback); 314 } 315 ExceptionState caught_exc_state(&scope, *caught_exc_state_obj); 316 Object type(&scope, caught_exc_state.type()); 317 Object value(&scope, caught_exc_state.value()); 318 Object traceback(&scope, caught_exc_state.traceback()); 319 return thread->runtime()->newTupleWith3(type, value, traceback); 320} 321 322RawObject FUNC(sys, intern)(Thread* thread, Arguments args) { 323 HandleScope scope(thread); 324 Object string(&scope, args.get(0)); 325 if (!thread->runtime()->isInstanceOfStr(*string)) { 326 return thread->raiseRequiresType(string, ID(str)); 327 } 328 if (!string.isStr()) { 329 return thread->raiseWithFmt(LayoutId::kTypeError, "can't intern %T", 330 &string); 331 } 332 return Runtime::internStr(thread, string); 333} 334 335RawObject FUNC(sys, getrecursionlimit)(Thread* thread, Arguments) { 336 return thread->runtime()->newInt(thread->recursionLimit()); 337} 338 339RawObject FUNC(sys, is_finalizing)(Thread* thread, Arguments) { 340 return Bool::fromBool(thread->runtime()->isFinalizing()); 341} 342 343RawObject FUNC(sys, setrecursionlimit)(Thread* thread, Arguments args) { 344 HandleScope scope(thread); 345 Int limit(&scope, args.get(0)); 346 OptInt<int> opt_val = limit.asInt<int>(); 347 if (opt_val.error != CastError::None) { 348 return thread->raiseWithFmt(LayoutId::kOverflowError, 349 "Python int too large to convert to C int"); 350 } 351 352 // TODO(T62600497) Raise RecursionError if new limit is too low at current 353 // recursion depth 354 355 thread->setRecursionLimit(opt_val.value); 356 return NoneType::object(); 357} 358 359RawObject FUNC(sys, set_asyncgen_hooks)(Thread* thread, Arguments args) { 360 HandleScope scope(thread); 361 Object finalizer(&scope, args.get(1)); 362 Runtime* runtime = thread->runtime(); 363 Object first_iter(&scope, args.get(0)); 364 if (!first_iter.isUnbound()) { 365 if (!first_iter.isNoneType() && !runtime->isCallable(thread, first_iter)) { 366 return thread->raiseWithFmt(LayoutId::kTypeError, 367 "callable firstiter expected, got %T", 368 &first_iter); 369 } 370 thread->setAsyncgenHooksFirstIter(*first_iter); 371 } 372 if (!finalizer.isUnbound()) { 373 if (!finalizer.isNoneType() && !runtime->isCallable(thread, finalizer)) { 374 return thread->raiseWithFmt(LayoutId::kTypeError, 375 "callable finalizer expected, got %T", 376 &finalizer); 377 } 378 thread->setAsyncgenHooksFinalizer(*finalizer); 379 } 380 return NoneType::object(); 381} 382 383} // namespace py