File: | build/../torch/csrc/serialization.cpp |
Warning: | line 45, column 19 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 PyImport_ImportModule |
2 | struct _object; |
3 | typedef struct _object PyObject; |
4 | PyObject* clang_analyzer_PyObject_New_Reference(); |
5 | PyObject* PyImport_ImportModule(const char *name) { |
6 | return clang_analyzer_PyObject_New_Reference(); |
7 | } |
8 | #else |
9 | #warning "API PyImport_ImportModule is defined as a macro." |
10 | #endif |