@@ -27,22 +27,24 @@ int (*PyOS_InputHook)(void) = NULL;
27
27
except if PyOS_InterruptOccurred() returns true. */
28
28
29
29
static int
30
- my_fgets (char * buf , int len , FILE * fp )
30
+ my_fgets (PyThreadState * tstate , char * buf , int len , FILE * fp )
31
31
{
32
32
#ifdef MS_WINDOWS
33
33
HANDLE hInterruptEvent ;
34
34
#endif
35
- char * p ;
36
- int err ;
37
35
while (1 ) {
38
- if (PyOS_InputHook != NULL )
36
+ if (PyOS_InputHook != NULL ) {
39
37
(void )(PyOS_InputHook )();
38
+ }
39
+
40
40
errno = 0 ;
41
41
clearerr (fp );
42
- p = fgets (buf , len , fp );
43
- if (p != NULL )
42
+ char * p = fgets (buf , len , fp );
43
+ if (p != NULL ) {
44
44
return 0 ; /* No error */
45
- err = errno ;
45
+ }
46
+ int err = errno ;
47
+
46
48
#ifdef MS_WINDOWS
47
49
/* Ctrl-C anywhere on the line or Ctrl-Z if the only character
48
50
on a line will set ERROR_OPERATION_ABORTED. Under normal
@@ -68,22 +70,26 @@ my_fgets(char *buf, int len, FILE *fp)
68
70
}
69
71
}
70
72
#endif /* MS_WINDOWS */
73
+
71
74
if (feof (fp )) {
72
75
clearerr (fp );
73
76
return -1 ; /* EOF */
74
77
}
78
+
75
79
#ifdef EINTR
76
80
if (err == EINTR ) {
77
- int s ;
78
- PyEval_RestoreThread (_PyOS_ReadlineTState );
79
- s = PyErr_CheckSignals ();
81
+ PyEval_RestoreThread (tstate );
82
+ int s = PyErr_CheckSignals ();
80
83
PyEval_SaveThread ();
81
- if (s < 0 )
82
- return 1 ;
83
- /* try again */
84
+
85
+ if (s < 0 ) {
86
+ return 1 ;
87
+ }
88
+ /* try again */
84
89
continue ;
85
90
}
86
91
#endif
92
+
87
93
if (PyOS_InterruptOccurred ()) {
88
94
return 1 ; /* Interrupt */
89
95
}
@@ -98,7 +104,7 @@ my_fgets(char *buf, int len, FILE *fp)
98
104
extern char _get_console_type (HANDLE handle );
99
105
100
106
char *
101
- _PyOS_WindowsConsoleReadline (HANDLE hStdIn )
107
+ _PyOS_WindowsConsoleReadline (PyThreadState * tstate , HANDLE hStdIn )
102
108
{
103
109
static wchar_t wbuf_local [1024 * 16 ];
104
110
const DWORD chunk_size = 1024 ;
@@ -133,11 +139,12 @@ _PyOS_WindowsConsoleReadline(HANDLE hStdIn)
133
139
if (WaitForSingleObjectEx (hInterruptEvent , 100 , FALSE)
134
140
== WAIT_OBJECT_0 ) {
135
141
ResetEvent (hInterruptEvent );
136
- PyEval_RestoreThread (_PyOS_ReadlineTState );
142
+ PyEval_RestoreThread (tstate );
137
143
s = PyErr_CheckSignals ();
138
144
PyEval_SaveThread ();
139
- if (s < 0 )
145
+ if (s < 0 ) {
140
146
goto exit ;
147
+ }
141
148
}
142
149
break ;
143
150
}
@@ -150,17 +157,22 @@ _PyOS_WindowsConsoleReadline(HANDLE hStdIn)
150
157
if (wbuf == wbuf_local ) {
151
158
wbuf [total_read ] = '\0' ;
152
159
wbuf = (wchar_t * )PyMem_RawMalloc (wbuflen * sizeof (wchar_t ));
153
- if (wbuf )
160
+ if (wbuf ) {
154
161
wcscpy_s (wbuf , wbuflen , wbuf_local );
162
+ }
155
163
else {
164
+ PyEval_RestoreThread (tstate );
156
165
PyErr_NoMemory ();
166
+ PyEval_SaveThread ();
157
167
goto exit ;
158
168
}
159
169
}
160
170
else {
161
171
wchar_t * tmp = PyMem_RawRealloc (wbuf , wbuflen * sizeof (wchar_t ));
162
172
if (tmp == NULL ) {
173
+ PyEval_RestoreThread (tstate );
163
174
PyErr_NoMemory ();
175
+ PyEval_SaveThread ();
164
176
goto exit ;
165
177
}
166
178
wbuf = tmp ;
@@ -169,33 +181,45 @@ _PyOS_WindowsConsoleReadline(HANDLE hStdIn)
169
181
170
182
if (wbuf [0 ] == '\x1a' ) {
171
183
buf = PyMem_RawMalloc (1 );
172
- if (buf )
184
+ if (buf ) {
173
185
buf [0 ] = '\0' ;
186
+ }
174
187
else {
188
+ PyEval_RestoreThread (tstate );
175
189
PyErr_NoMemory ();
190
+ PyEval_SaveThread ();
176
191
}
177
192
goto exit ;
178
193
}
179
194
180
- u8len = WideCharToMultiByte (CP_UTF8 , 0 , wbuf , total_read , NULL , 0 , NULL , NULL );
195
+ u8len = WideCharToMultiByte (CP_UTF8 , 0 ,
196
+ wbuf , total_read ,
197
+ NULL , 0 ,
198
+ NULL , NULL );
181
199
buf = PyMem_RawMalloc (u8len + 1 );
182
200
if (buf == NULL ) {
201
+ PyEval_RestoreThread (tstate );
183
202
PyErr_NoMemory ();
203
+ PyEval_SaveThread ();
184
204
goto exit ;
185
205
}
186
- u8len = WideCharToMultiByte (CP_UTF8 , 0 , wbuf , total_read , buf , u8len , NULL , NULL );
206
+
207
+ u8len = WideCharToMultiByte (CP_UTF8 , 0 ,
208
+ wbuf , total_read ,
209
+ buf , u8len ,
210
+ NULL , NULL );
187
211
buf [u8len ] = '\0' ;
188
212
189
213
exit :
190
- if (wbuf != wbuf_local )
214
+ if (wbuf != wbuf_local ) {
191
215
PyMem_RawFree (wbuf );
216
+ }
192
217
193
218
if (err ) {
194
- PyEval_RestoreThread (_PyOS_ReadlineTState );
219
+ PyEval_RestoreThread (tstate );
195
220
PyErr_SetFromWindowsErr (err );
196
221
PyEval_SaveThread ();
197
222
}
198
-
199
223
return buf ;
200
224
}
201
225
@@ -209,6 +233,8 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
209
233
{
210
234
size_t n ;
211
235
char * p , * pr ;
236
+ PyThreadState * tstate = _PyOS_ReadlineTState ;
237
+ assert (tstate != NULL );
212
238
213
239
#ifdef MS_WINDOWS
214
240
if (!Py_LegacyWindowsStdioFlag && sys_stdin == stdin ) {
@@ -230,7 +256,9 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
230
256
if (wlen ) {
231
257
wbuf = PyMem_RawMalloc (wlen * sizeof (wchar_t ));
232
258
if (wbuf == NULL ) {
259
+ PyEval_RestoreThread (tstate );
233
260
PyErr_NoMemory ();
261
+ PyEval_SaveThread ();
234
262
return NULL ;
235
263
}
236
264
wlen = MultiByteToWideChar (CP_UTF8 , 0 , prompt , -1 ,
@@ -249,24 +277,27 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
249
277
}
250
278
}
251
279
clearerr (sys_stdin );
252
- return _PyOS_WindowsConsoleReadline (hStdIn );
280
+ return _PyOS_WindowsConsoleReadline (tstate , hStdIn );
253
281
}
254
282
}
255
283
#endif
256
284
257
285
n = 100 ;
258
286
p = (char * )PyMem_RawMalloc (n );
259
287
if (p == NULL ) {
288
+ PyEval_RestoreThread (tstate );
260
289
PyErr_NoMemory ();
290
+ PyEval_SaveThread ();
261
291
return NULL ;
262
292
}
263
293
264
294
fflush (sys_stdout );
265
- if (prompt )
295
+ if (prompt ) {
266
296
fprintf (stderr , "%s" , prompt );
297
+ }
267
298
fflush (stderr );
268
299
269
- switch (my_fgets (p , (int )n , sys_stdin )) {
300
+ switch (my_fgets (tstate , p , (int )n , sys_stdin )) {
270
301
case 0 : /* Normal case */
271
302
break ;
272
303
case 1 : /* Interrupt */
@@ -278,29 +309,40 @@ PyOS_StdioReadline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
278
309
* p = '\0' ;
279
310
break ;
280
311
}
312
+
281
313
n = strlen (p );
282
314
while (n > 0 && p [n - 1 ] != '\n' ) {
283
315
size_t incr = n + 2 ;
284
316
if (incr > INT_MAX ) {
285
317
PyMem_RawFree (p );
318
+ PyEval_RestoreThread (tstate );
286
319
PyErr_SetString (PyExc_OverflowError , "input line too long" );
320
+ PyEval_SaveThread ();
287
321
return NULL ;
288
322
}
323
+
289
324
pr = (char * )PyMem_RawRealloc (p , n + incr );
290
325
if (pr == NULL ) {
291
326
PyMem_RawFree (p );
327
+ PyEval_RestoreThread (tstate );
292
328
PyErr_NoMemory ();
329
+ PyEval_SaveThread ();
293
330
return NULL ;
294
331
}
295
332
p = pr ;
296
- if (my_fgets (p + n , (int )incr , sys_stdin ) != 0 )
333
+
334
+ if (my_fgets (tstate , p + n , (int )incr , sys_stdin ) != 0 ) {
297
335
break ;
336
+ }
298
337
n += strlen (p + n );
299
338
}
339
+
300
340
pr = (char * )PyMem_RawRealloc (p , n + 1 );
301
341
if (pr == NULL ) {
302
342
PyMem_RawFree (p );
343
+ PyEval_RestoreThread (tstate );
303
344
PyErr_NoMemory ();
345
+ PyEval_SaveThread ();
304
346
return NULL ;
305
347
}
306
348
return pr ;
@@ -323,7 +365,8 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
323
365
char * rv , * res ;
324
366
size_t len ;
325
367
326
- if (_PyOS_ReadlineTState == _PyThreadState_GET ()) {
368
+ PyThreadState * tstate = _PyThreadState_GET ();
369
+ if (_PyOS_ReadlineTState == tstate ) {
327
370
PyErr_SetString (PyExc_RuntimeError ,
328
371
"can't re-enter readline" );
329
372
return NULL ;
@@ -342,7 +385,7 @@ PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
342
385
}
343
386
}
344
387
345
- _PyOS_ReadlineTState = _PyThreadState_GET () ;
388
+ _PyOS_ReadlineTState = tstate ;
346
389
Py_BEGIN_ALLOW_THREADS
347
390
PyThread_acquire_lock (_PyOS_ReadlineLock , 1 );
348
391
0 commit comments