| File: | build/../torch/csrc/serialization.cpp |
| Warning: | line 81, column 24 PyObject ownership leak with reference count of 1 |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | #include <torch/csrc/python_headers.h> | ||||
| 2 | #include <system_error> | ||||
| 3 | |||||
| 4 | #include <torch/csrc/THP.h> | ||||
| 5 | #include <torch/csrc/serialization.h> | ||||
| 6 | |||||
| 7 | template <class io> | ||||
| 8 | ssize_t doPartialRead(io fildes, void* buf, size_t nbytes); | ||||
| 9 | |||||
| 10 | template <class io> | ||||
| 11 | ssize_t doPartialWrite(io fildes, void* buf, size_t nbytes); | ||||
| 12 | |||||
| 13 | static ssize_t doPartialPythonReadBuffered(PyObject* fildes, void* buf, size_t nbytes); | ||||
| 14 | static ssize_t doPartialPythonReadInto(PyObject* fildes, void* buf, size_t nbytes); | ||||
| 15 | static ssize_t doPartialPythonWrite(PyObject* fildes, void* buf, size_t nbytes); | ||||
| 16 | |||||
| 17 | template <> | ||||
| 18 | ssize_t doPartialRead<int>(int fildes, void* buf, size_t nbytes) { | ||||
| 19 | return read(fildes, buf, nbytes); | ||||
| 20 | } | ||||
| 21 | |||||
| 22 | template <> | ||||
| 23 | ssize_t doPartialRead<PyObject*>(PyObject* fildes, void* buf, size_t nbytes) { | ||||
| 24 | // Try to use fildes.readinto() instead of fildes.read() | ||||
| 25 | // because it is more memory efficient. | ||||
| 26 | // TODO: Stop calling PyObject_HasAttrString() in a loop on our read loop | ||||
| 27 | auto has_readinto = PyObject_HasAttrString(fildes, "readinto") == 1; | ||||
| 28 | if (has_readinto) { | ||||
| 29 | return doPartialPythonReadInto(fildes, buf, nbytes); | ||||
| 30 | } | ||||
| 31 | return doPartialPythonReadBuffered(fildes, buf, nbytes); | ||||
| 32 | } | ||||
| 33 | |||||
| 34 | template <> | ||||
| 35 | ssize_t doPartialWrite<int>(int fildes, void* buf, size_t nbytes) { | ||||
| 36 | return write(fildes, buf, nbytes); | ||||
| 37 | } | ||||
| 38 | |||||
| 39 | template <> | ||||
| 40 | ssize_t doPartialWrite<PyObject*>(PyObject* fildes, void* buf, size_t nbytes) { | ||||
| 41 | return doPartialPythonWrite(fildes, buf, nbytes); | ||||
| 42 | } | ||||
| 43 | |||||
| 44 | static inline bool isUnsupportedOperation() { | ||||
| 45 | THPObjectPtr io(PyImport_ImportModule("io")); | ||||
| 46 | if (!io) throw python_error(); | ||||
| 47 | THPObjectPtr exception(PyObject_GetAttrString(io, "UnsupportedOperation")); | ||||
| 48 | if (!exception) throw python_error(); | ||||
| 49 | return PyErr_ExceptionMatches(exception.get()); | ||||
| 50 | } | ||||
| 51 | |||||
| 52 | // Call Python fildes.read(nbytes) and copy it to buf. | ||||
| 53 | static inline ssize_t doPartialPythonReadBuffered(PyObject* fildes, void* buf, size_t raw_nbytes) { | ||||
| 54 | // If we request a large amount of data, f.read() will internally try to | ||||
| 55 | // allocate a buffer of that size. This is counterproductive, because | ||||
| 56 | // it's not the buffer we ultimately want to write the data into. Read | ||||
| 57 | // less than that and avoid allocating too much extra memory. | ||||
| 58 | // TODO: Maybe 260 KB is a bit small... | ||||
| 59 | const size_t nbytes = std::min<size_t>(raw_nbytes, 262144u); // 2^18 (~260 KB) | ||||
| 60 | |||||
| 61 | THPObjectPtr r(PyObject_CallMethod(fildes, "read", "i", nbytes)); | ||||
| 62 | if (!r) throw python_error(); | ||||
| 63 | |||||
| 64 | auto size = PyBytes_GET_SIZE(r.get())((((PyVarObject*)(r.get()))->ob_size)); | ||||
| 65 | const void* py_buf = PyBytes_AsString(r.get()); | ||||
| 66 | |||||
| 67 | // we read EOF | ||||
| 68 | if (size == 0) { | ||||
| 69 | return 0; | ||||
| 70 | } | ||||
| 71 | |||||
| 72 | // Slurp it into the buffer we actually want | ||||
| 73 | memcpy(buf, py_buf, size); | ||||
| 74 | |||||
| 75 | return size; | ||||
| 76 | } | ||||
| 77 | |||||
| 78 | // Either does fildes.readinto(buf) or fildes.write(buf) | ||||
| 79 | static inline ssize_t doPartialPythonIO(PyObject* fildes, void* buf, size_t nbytes, bool is_read) { | ||||
| 80 | auto rw_flag = is_read
| ||||
| 81 | THPObjectPtr memview(PyMemoryView_FromMemory( | ||||
| |||||
| 82 | reinterpret_cast<char*>(buf), nbytes, rw_flag)); | ||||
| 83 | if (!memview) throw python_error(); | ||||
| 84 | |||||
| 85 | std::string method = "write"; | ||||
| 86 | if (is_read
| ||||
| 87 | method = "readinto"; | ||||
| 88 | } | ||||
| 89 | THPObjectPtr r(PyObject_CallMethod(fildes, method.c_str(), "O", memview.get())); | ||||
| 90 | if (r) { | ||||
| 91 | return PyLong_AsSsize_t(r.get()); | ||||
| 92 | } | ||||
| 93 | |||||
| 94 | // fildes.readinto can return UnsupportedOperation so fall back to fildes.read. | ||||
| 95 | if (is_read
| ||||
| 96 | PyErr_Clear(); | ||||
| 97 | return doPartialPythonReadBuffered(fildes, buf, nbytes); | ||||
| 98 | } | ||||
| 99 | throw python_error(); | ||||
| 100 | } | ||||
| 101 | |||||
| 102 | // Call Python fildes.readinto(buf) | ||||
| 103 | static ssize_t doPartialPythonReadInto(PyObject* fildes, void* buf, size_t nbytes) { | ||||
| 104 | return doPartialPythonIO(fildes, buf, nbytes, /* is_read */ true); | ||||
| 105 | } | ||||
| 106 | |||||
| 107 | // Call Python fildes.write(buf) | ||||
| 108 | static ssize_t doPartialPythonWrite(PyObject* fildes, void* buf, size_t nbytes) { | ||||
| 109 | return doPartialPythonIO(fildes, buf, nbytes, /* is_read */ false); | ||||
| 110 | } | ||||
| 111 | |||||
| 112 | // Requires that we read EXACTLY nbytes; fails if we don't. | ||||
| 113 | template <typename io> | ||||
| 114 | void doRead(io fildes, void* raw_buf, size_t nbytes) { | ||||
| 115 | char* buf = static_cast<char*>(raw_buf); | ||||
| 116 | while (nbytes > 0) { | ||||
| 117 | errno(*__errno_location ()) = 0; // doPartialRead may not set errno | ||||
| 118 | // we read in 1GB blocks to avoid bugs on Mac OS X Lion | ||||
| 119 | // see https://github.com/pytorch/pytorch/issues/1031 for more details | ||||
| 120 | ssize_t r = doPartialRead(fildes, buf, std::min<size_t>(nbytes, 1073741824)); | ||||
| 121 | if (r < 0) { | ||||
| 122 | int err = errno(*__errno_location ()); | ||||
| 123 | TORCH_INTERNAL_ASSERT(err != 0, "read(): impossible! r < 0, but no errno was set")if ((__builtin_expect(static_cast<bool>(!(err != 0)), 0 ))) { ::c10::detail::torchInternalAssertFail( __func__, "../torch/csrc/serialization.cpp" , static_cast<uint32_t>(123), "err != 0" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "123" ", please report a bug to PyTorch. " , c10::str("read(): impossible! r < 0, but no errno was set" )); }; | ||||
| 124 | TORCH_INTERNAL_ASSERT(err != EAGAIN, "read(): non-blocking fd ", fildes,if ((__builtin_expect(static_cast<bool>(!(err != 11)), 0 ))) { ::c10::detail::torchInternalAssertFail( __func__, "../torch/csrc/serialization.cpp" , static_cast<uint32_t>(125), "err != EAGAIN" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "125" ", please report a bug to PyTorch. " , c10::str("read(): non-blocking fd ", fildes, " read EAGAIN; cowardly refusing to spin-wait" )); } | ||||
| 125 | " read EAGAIN; cowardly refusing to spin-wait")if ((__builtin_expect(static_cast<bool>(!(err != 11)), 0 ))) { ::c10::detail::torchInternalAssertFail( __func__, "../torch/csrc/serialization.cpp" , static_cast<uint32_t>(125), "err != EAGAIN" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "125" ", please report a bug to PyTorch. " , c10::str("read(): non-blocking fd ", fildes, " read EAGAIN; cowardly refusing to spin-wait" )); }; | ||||
| 126 | if (err == EINTR4) { | ||||
| 127 | continue; | ||||
| 128 | } else { | ||||
| 129 | AT_ERROR("read(): fd ", fildes, " failed with ", strerror(err))do { ::c10::detail::deprecated_AT_ERROR(); if ((__builtin_expect (static_cast<bool>(!(false)), 0))) { ::c10::detail::torchCheckFail ( __func__, "../torch/csrc/serialization.cpp", static_cast< uint32_t>(129), (::c10::detail::torchCheckMsgImpl( "Expected " "false" " to be true, but got false. " "(Could this error message be improved? If so, " "please report an enhancement request to PyTorch.)", ::c10:: str("read(): fd ", fildes, " failed with ", strerror(err))))) ; }; } while (false); | ||||
| 130 | } | ||||
| 131 | } else if (r == 0) { | ||||
| 132 | break; | ||||
| 133 | } | ||||
| 134 | buf += r; | ||||
| 135 | // This is guaranteed by POSIX, but I just want to be double-sure | ||||
| 136 | // to not underflow a signed integer. | ||||
| 137 | AT_ASSERT(static_cast<size_t>(r) <= nbytes)do { ::c10::detail::deprecated_AT_ASSERT(); if ((__builtin_expect (static_cast<bool>(!(static_cast<size_t>(r) <= nbytes)), 0))) { ::c10::detail::torchInternalAssertFail( __func__ , "../torch/csrc/serialization.cpp", static_cast<uint32_t> (137), "static_cast<size_t>(r) <= nbytes" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "137" ", please report a bug to PyTorch. " , c10::str()); }; } while (false); | ||||
| 138 | nbytes -= r; | ||||
| 139 | } | ||||
| 140 | if (nbytes != 0) { | ||||
| 141 | AT_ERROR("unexpected EOF, expected ", nbytes, " more bytes. The file might be corrupted.")do { ::c10::detail::deprecated_AT_ERROR(); if ((__builtin_expect (static_cast<bool>(!(false)), 0))) { ::c10::detail::torchCheckFail ( __func__, "../torch/csrc/serialization.cpp", static_cast< uint32_t>(141), (::c10::detail::torchCheckMsgImpl( "Expected " "false" " to be true, but got false. " "(Could this error message be improved? If so, " "please report an enhancement request to PyTorch.)", ::c10:: str("unexpected EOF, expected ", nbytes, " more bytes. The file might be corrupted." )))); }; } while (false); | ||||
| 142 | } | ||||
| 143 | } | ||||
| 144 | |||||
| 145 | template <typename io> | ||||
| 146 | void doWrite(io fildes, void* raw_buf, size_t nbytes) { | ||||
| 147 | char* buf = static_cast<char*>(raw_buf); | ||||
| 148 | while (nbytes > 0) { | ||||
| |||||
| 149 | errno(*__errno_location ()) = 0; // doPartialWrite may not set errno | ||||
| 150 | // we write in 1GB blocks to avoid bugs on Mac OS X Lion | ||||
| 151 | // see https://github.com/pytorch/pytorch/issues/1031 for more details | ||||
| 152 | ssize_t r = doPartialWrite(fildes, buf, std::min<size_t>(nbytes, 1073741824)); | ||||
| 153 | if (r < 0) { | ||||
| 154 | int err = errno(*__errno_location ()); | ||||
| 155 | TORCH_INTERNAL_ASSERT(err != 0, "write(): impossible! r < 0, but no errno was set")if ((__builtin_expect(static_cast<bool>(!(err != 0)), 0 ))) { ::c10::detail::torchInternalAssertFail( __func__, "../torch/csrc/serialization.cpp" , static_cast<uint32_t>(155), "err != 0" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "155" ", please report a bug to PyTorch. " , c10::str("write(): impossible! r < 0, but no errno was set" )); }; | ||||
| 156 | TORCH_INTERNAL_ASSERT(err != EAGAIN, "write(): non-blocking fd ", fildes,if ((__builtin_expect(static_cast<bool>(!(err != 11)), 0 ))) { ::c10::detail::torchInternalAssertFail( __func__, "../torch/csrc/serialization.cpp" , static_cast<uint32_t>(157), "err != EAGAIN" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "157" ", please report a bug to PyTorch. " , c10::str("write(): non-blocking fd ", fildes, " read EAGAIN; cowardly refusing to spin-wait" )); } | ||||
| 157 | " read EAGAIN; cowardly refusing to spin-wait")if ((__builtin_expect(static_cast<bool>(!(err != 11)), 0 ))) { ::c10::detail::torchInternalAssertFail( __func__, "../torch/csrc/serialization.cpp" , static_cast<uint32_t>(157), "err != EAGAIN" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "157" ", please report a bug to PyTorch. " , c10::str("write(): non-blocking fd ", fildes, " read EAGAIN; cowardly refusing to spin-wait" )); }; | ||||
| 158 | if (err == EINTR4) { | ||||
| 159 | continue; | ||||
| 160 | } else { | ||||
| 161 | AT_ERROR("write(): fd ", fildes, " failed with ", strerror(err))do { ::c10::detail::deprecated_AT_ERROR(); if ((__builtin_expect (static_cast<bool>(!(false)), 0))) { ::c10::detail::torchCheckFail ( __func__, "../torch/csrc/serialization.cpp", static_cast< uint32_t>(161), (::c10::detail::torchCheckMsgImpl( "Expected " "false" " to be true, but got false. " "(Could this error message be improved? If so, " "please report an enhancement request to PyTorch.)", ::c10:: str("write(): fd ", fildes, " failed with ", strerror(err)))) ); }; } while (false); | ||||
| 162 | } | ||||
| 163 | } | ||||
| 164 | buf += r; | ||||
| 165 | AT_ASSERT(static_cast<size_t>(r) <= nbytes)do { ::c10::detail::deprecated_AT_ASSERT(); if ((__builtin_expect (static_cast<bool>(!(static_cast<size_t>(r) <= nbytes)), 0))) { ::c10::detail::torchInternalAssertFail( __func__ , "../torch/csrc/serialization.cpp", static_cast<uint32_t> (165), "static_cast<size_t>(r) <= nbytes" "INTERNAL ASSERT FAILED at " "\"../torch/csrc/serialization.cpp\"" ":" "165" ", please report a bug to PyTorch. " , c10::str()); }; } while (false); | ||||
| 166 | nbytes -= r; | ||||
| 167 | } | ||||
| 168 | } | ||||
| 169 | |||||
| 170 | // NOLINTNEXTLINE(bugprone-suspicious-include) | ||||
| 171 | #include <torch/csrc/generic/serialization.cpp> | ||||
| 172 | #include <TH/THGenerateAllTypes.h> | ||||
| 173 | |||||
| 174 | // NOLINTNEXTLINE(bugprone-suspicious-include) | ||||
| 175 | #include <torch/csrc/generic/serialization.cpp> | ||||
| 176 | #include <TH/THGenerateComplexTypes.h> | ||||
| 177 | |||||
| 178 | // NOLINTNEXTLINE(bugprone-suspicious-include) | ||||
| 179 | #include <torch/csrc/generic/serialization.cpp> | ||||
| 180 | #include <TH/THGenerateHalfType.h> | ||||
| 181 | |||||
| 182 | // NOLINTNEXTLINE(bugprone-suspicious-include) | ||||
| 183 | #include <torch/csrc/generic/serialization.cpp> | ||||
| 184 | #include <TH/THGenerateBFloat16Type.h> | ||||
| 185 | |||||
| 186 | // NOLINTNEXTLINE(bugprone-suspicious-include) | ||||
| 187 | #include <torch/csrc/generic/serialization.cpp> | ||||
| 188 | #include <TH/THGenerateBoolType.h> | ||||
| 189 | |||||
| 190 | // NOLINTNEXTLINE(bugprone-suspicious-include) | ||||
| 191 | #include <torch/csrc/generic/serialization.cpp> | ||||
| 192 | #include <TH/THGenerateQTypes.h> |
| 1 | #ifndef PyMemoryView_FromMemory |
| 2 | struct _object; |
| 3 | typedef struct _object PyObject; |
| 4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
| 5 | PyObject *PyMemoryView_FromMemory(char *mem, Py_ssize_t size, int flags) { |
| 6 | return clang_analyzer_PyObject_New_Reference(); |
| 7 | } |
| 8 | #else |
| 9 | #warning "API PyMemoryView_FromMemory is defined as a macro." |
| 10 | #endif |