8000 ports/unix: implement PEP 475 · micropython/micropython@5f204d7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5f204d7

Browse files
committed
ports/unix: implement PEP 475
https://www.python.org/dev/peps/pep-0475/ This implements something similar to PEP 475 on the unix port. There are a few differences from the CPython implementation: - Since we call mp_handle_pending(), addition functions could be called if MICROPY_ENABLE_SCHEDULER is enabled, not just signal handlers. - CPython only handles signal on the main thread, so other threads will raise InterruptedError instead of retrying. On MicroPython, mp_handle_pending() will currently raise exceptions on any thread.
1 parent 8db5d2d commit 5f204d7

File tree

11 files changed

+374
-210
lines changed

11 files changed

+374
-210
lines changed

extmod/vfs_posix.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -290,11 +290,19 @@ STATIC mp_obj_t vfs_posix_stat(mp_obj_t self_in, mp_obj_t path_in) {
290290
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
291291
struct stat sb;
292292
const char *path = vfs_posix_get_path_str(self, path_in);
293-
MP_THREAD_GIL_EXIT();
294-
int ret = stat(path, &sb);
295-
MP_THREAD_GIL_ENTER();
296-
if (ret != 0) {
297-
mp_raise_OSError(errno);
293+
for (;;) {
294+
MP_THREAD_GIL_EXIT();
295+
int ret = stat(path, &sb);
296+
MP_THREAD_GIL_ENTER();
297+
if (ret == -1) {
298+
int err = errno;
299+
if (err == EINTR) {
300+
mp_handle_pending(true);
301+
continue;
302+
}
303+
mp_raise_OSError(err);
304+
}
305+
break;
298306
}
299307
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
300308
t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.st_mode);
@@ -335,11 +343,19 @@ STATIC mp_obj_t vfs_posix_statvfs(mp_obj_t self_in, mp_obj_t path_in) {
335343
mp_obj_vfs_posix_t *self = MP_OBJ_TO_PTR(self_in);
336344
STRUCT_STATVFS sb;
337345
const char *path = vfs_posix_get_path_str(self, path_in);
338-
MP_THREAD_GIL_EXIT();
339-
int ret = STATVFS(path, &sb);
340-
MP_THREAD_GIL_ENTER();
341-
if (ret != 0) {
342-
mp_raise_OSError(errno);
346+
for (;;) {
347+
MP_THREAD_GIL_EXIT();
348+
int ret = STATVFS(path, &sb);
349+
MP_THREAD_GIL_ENTER();
350+
if (ret == -1) {
351+
int err = errno;
352+
if (err == EINTR) {
353+
mp_handle_pending(true);
354+
continue;
355+
}
356+
mp_raise_OSError(err);
357+
}
358+
break;
343359
}
344360
mp_obj_tuple_t *t = MP_OBJ_TO_PTR(mp_obj_new_tuple(10, NULL));
345361
t->items[0] = MP_OBJ_NEW_SMALL_INT(sb.f_bsize);

extmod/vfs_posix_file.c

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -101,14 +101,21 @@ mp_obj_t mp_vfs_posix_file_open(const mp_obj_type_t *type, mp_obj_t file_in, mp_
101101
}
102102

103103
const char *fname = mp_obj_str_get_str(fid);
104-
MP_THREAD_GIL_EXIT();
105-
int fd = open(fname, mode_x | mode_rw, 0644);
106-
MP_THREAD_GIL_ENTER();
107-
if (fd == -1) {
108-
mp_raise_OSError(errno);
104+
for (;;) {
105+
MP_THREAD_GIL_EXIT();
106+
int fd = open(fname, mode_x | mode_rw, 0644);
107+
MP_THREAD_GIL_ENTER();
108+
if (fd == -1) {
109+
int err = errno;
110+
if (err == EINTR) {
111+
mp_handle_pending(true);
112+
continue;
113+
}
114+
mp_raise_OSError(err);
115+
}
116+
o->fd = fd;
117+
return MP_OBJ_FROM_PTR(o);
109118
}
110-
o->fd = fd;
111-
return MP_OBJ_FROM_PTR(o);
112119
}
113120

114121
STATIC mp_obj_t vfs_posix_file_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
@@ -138,14 +145,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(vfs_posix_file___exit___obj, 4, 4, vf
138145
STATIC mp_uint_t vfs_posix_file_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
139146
mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in);
140147
check_fd_is_open(o);
141-
MP_THREAD_GIL_EXIT();
142-
mp_int_t r = read(o->fd, buf, size);
143-
MP_THREAD_GIL_ENTER();
144-
if (r == -1) {
145-
*errcode = errno;
146-
return MP_STREAM_ERROR;
148+
for (;;) {
149+
MP_THREAD_GIL_EXIT();
150+
ssize_t r = read(o->fd, buf, size);
151+
MP_THREAD_GIL_ENTER();
152+
if (r == -1) {
153+
int err = errno;
154+
if (err == EINTR) {
155+
mp_handle_pending(true);
156+
continue;
157+
}
158+
*errcode = err;
159+
return MP_STREAM_ERROR;
160+
}
161+
return (mp_uint_t)r;
147162
}
148-
return r;
149163
}
150164

151165
STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
@@ -157,37 +171,43 @@ STATIC mp_uint_t vfs_posix_file_write(mp_obj_t o_in, const void *buf, mp_uint_t
157171
return size;
158172
}
159173
#endif
160-
mp_int_t r = write(o->fd, buf, size);
161-
while (r == -1 && errno == EINTR) {
162-
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
163-
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
164-
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
165-
nlr_raise(obj);
166-
}
174+
for (;;) {
167175
MP_THREAD_GIL_EXIT();
168-
r = write(o->fd, buf, size);
176+
ssize_t r = write(o->fd, buf, size);
169177
MP_THREAD_GIL_ENTER();
178+
if (r == -1) {
179+
int err = errno;
180+
if (err == EINTR) {
181+
mp_handle_pending(true);
182+
continue;
183+
}
184+
*errcode = err;
185+
return MP_STREAM_ERROR;
186+
}
187+
return (mp_uint_t)r;
170188
}
171-
if (r == -1) {
172-
*errcode = errno;
173-
return MP_STREAM_ERROR;
174-
}
175-
return r;
176189
}
177190

178191
STATIC mp_uint_t vfs_posix_file_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
179192
mp_obj_vfs_posix_file_t *o = MP_OBJ_TO_PTR(o_in);
180193
check_fd_is_open(o);
181194
switch (request) {
182195
case MP_STREAM_FLUSH:
183-
MP_THREAD_GIL_EXIT();
184-
int ret = fsync(o->fd);
185-
MP_THREAD_GIL_ENTER();
186-
if (ret == -1) {
187-
*errcode = errno;
188-
return MP_STREAM_ERROR;
196+
for (;;) {
197+
MP_THREAD_GIL_EXIT();
198+
int ret = fsync(o->fd);
199+
MP_THREAD_GIL_ENTER();
200+
if (ret == -1) {
201+
int err = errno;
202+
if (err == EINTR) {
203+
mp_handle_pending(true);
204+
continue;
205+
}
206+
*errcode = err;
207+
return MP_STREAM_ERROR;
208+
}
209+
return 0;
189210
}
190-
return 0;
191211
case MP_STREAM_SEEK: {
192212
struct mp_stream_seek_t *s = (struct mp_stream_seek_t *)arg;
193213
MP_THREAD_GIL_EXIT();

ports/unix/file.c

Lines changed: 60 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,21 @@ STATIC void fdfile_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kin
6666
STATIC mp_uint_t fdfile_read(mp_obj_t o_in, void *buf, mp_uint_t size, int *errcode) {
6767
mp_obj_fdfile_t *o = MP_OBJ_TO_PTR(o_in);
6868
check_fd_is_open(o);
69-
MP_THREAD_GIL_EXIT();
70-
mp_int_t r = read(o->fd, buf, size);
71-
MP_THREAD_GIL_ENTER();
72-
if (r == -1) {
73-
*errcode = errno;
74-
return MP_STREAM_ERROR;
69+
for (;;) {
70+
MP_THREAD_GIL_EXIT();
71+
ssize_t r = read(o->fd, buf, size);
72+
MP_THREAD_GIL_ENTER();
73+
if (r == -1) {
74+
int err = errno;
75+
if (err == EINTR) {
76+
mp_handle_pending(true);
77+
continue;
78+
}
79+
*errcode = err;
80+
return MP_STREAM_ERROR;
81+
}
82+
return (mp_uint_t)r;
7583
}
76-
return r;
7784
}
7885

7986
STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, int *errcode) {
@@ -85,24 +92,21 @@ STATIC mp_uint_t fdfile_write(mp_obj_t o_in, const void *buf, mp_uint_t size, in
8592
return size;
8693
}
8794
#endif
88-
MP_THREAD_GIL_EXIT();
89-
mp_int_t r = write(o->fd, buf, size);
90-
MP_THREAD_GIL_ENTER();
91-
while (r == -1 && errno == EINTR) {
92-
if (MP_STATE_VM(mp_pending_exception) != MP_OBJ_NULL) {
93-
mp_obj_t obj = MP_STATE_VM(mp_pending_exception);
94-
MP_STATE_VM(mp_pending_exception) = MP_OBJ_NULL;
95-
nlr_raise(obj);
96-
}
95+
for (;;) {
9796
MP_THREAD_GIL_EXIT();
98-
r = write(o->fd, buf, size);
97+
mp_int_t r = write(o->fd, buf, size);
9998
MP_THREAD_GIL_ENTER();
99+
if (r == -1) {
100+
int err = errno;
101+
if (err == EINTR) {
102+
mp_handle_pending(true);
103+
continue;
104+
}
105+
*errcode = err;
106+
return MP_STREAM_ERROR;
107+
}
108+
return r;
100109
}
101-
if (r == -1) {
102-
*errcode = errno;
103-
return MP_STREAM_ERROR;
104-
}
105-
return r;
106110
}
107111

108112
STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, int *errcode) {
@@ -122,21 +126,28 @@ STATIC mp_uint_t fdfile_ioctl(mp_obj_t o_in, mp_uint_t request, uintptr_t arg, i
122126
return 0;
123127
}
124128
case MP_STREAM_FLUSH:
125-
MP_THREAD_GIL_EXIT();
126-
int ret = fsync(o->fd);
127-
MP_THREAD_GIL_ENTER();
128-
if (ret == -1) {
129-
if (errno == EINVAL
130-
&& (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
131-
// fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that
132-
// error out. Because data is not buffered by us, and stdin/out/err.flush()
133-
// should just be a no-op.
134-
return 0;
129+
for (;;) {
130+
MP_THREAD_GIL_EXIT();
131+
int ret = fsync(o->fd);
132+
MP_THREAD_GIL_ENTER();
133+
if (ret == -1) {
134+
int err = errno;
135+
if (err == EINTR) {
136+
mp_handle_pending(true);
137+
continue;
138+
}
139+
if (err == EINVAL
140+
&& (o->fd == STDIN_FILENO || o->fd == STDOUT_FILENO || o->fd == STDERR_FILENO)) {
141+
// fsync(stdin/stdout/stderr) may fail with EINVAL, but don't propagate that
142+
// error out. Because data is not buffered by us, and stdin/out/err.flush()
143+
// should just be a no-op.
144+
return 0;
145+
}
146+
*errcode = err;
147+
return MP_STREAM_ERROR;
135148
}
136-
*errcode = errno;
137-
return MP_STREAM_ERROR;
149+
return 0;
138150
}
139-
return 0;
140151
case MP_STREAM_CLOSE:
141152
MP_THREAD_GIL_EXIT();
142153
close(o->fd);
@@ -219,14 +230,21 @@ STATIC mp_obj_t fdfile_open(const mp_obj_type_t *type, mp_arg_val_t *args) {
219230
}
220231

221232
const char *fname = mp_obj_str_get_str(fid);
222-
MP_THREAD_GIL_EXIT();
223-
int fd = open(fname, mode_x | mode_rw, 0644);
224-
MP_THREAD_GIL_ENTER();
225-
if (fd == -1) {
226-
mp_raise_OSError(errno);
233+
for (;;) {
234+
MP_THREAD_GIL_EXIT();
235+
int fd = open(fname, mode_x | mode_rw, 0644);
236+
MP_THREAD_GIL_ENTER();
237+
if (fd == -1) {
238+
int err = errno;
239+
if (err == EINTR) {
240+
mp_handle_pending(true);
241+
continue;
242+
}
243+
mp_raise_OSError(err);
244+
}
245+
o->fd = fd;
246+
return MP_OBJ_FROM_PTR(o);
227247
}
228-
o->fd = fd;
229-
return MP_OBJ_FROM_PTR(o);
230248
}
231249

232250
STATIC mp_obj_t fdfile_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {

ports/unix/input.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
* THE SOFTWARE.
2525
*/
2626

27+
#include <errno.h>
2728
#include <stdio.h>
2829
#include <stdlib.h>
2930
#include <string.h>
@@ -74,6 +75,9 @@ void prompt_read_history(void) {
7475
char c;
7576
int sz = read(fd, &c, 1);
7677
if (sz < 0) {
78+
if (errno == EINTR) {
79+
continue;
80+
}
7781
break;
7882
}
7983
if (< 8000 span class=pl-s1>sz == 0 || c == '\n') {
@@ -107,10 +111,8 @@ void prompt_write_history(void) {
107111
for (int i = MP_ARRAY_SIZE(MP_STATE_PORT(readline_hist)) - 1; i >= 0; i--) {
108112
const char *line = MP_STATE_PORT(readline_hist)[i];
109113
if (line != NULL) {
110-
int res;
111-
res = write(fd, line, strlen(line));
112-
res = write(fd, "\n", 1);
113-
(void)res;
114+
while (write(fd, line, strlen(line) == -1 && errno == EINTR));
115+
while (write(fd, "\n", 1) == -1 && errno == EINTR);
114116
}
115117
}
116118
close(fd);

ports/unix/main.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,16 @@ long heap_size = 1024 * 1024 * (sizeof(mp_uint_t) / 4);
6464

6565
STATIC void stderr_print_strn(void *env, const char *str, size_t len) {
6666
(void)env;
67-
MP_THREAD_GIL_EXIT();
68-
ssize_t dummy = write(STDERR_FILENO, str, len);
69-
MP_THREAD_GIL_ENTER();
67+
for (;;) {
68+
MP_THREAD_GIL_EXIT();
69+
ssize_t ret = write(STDERR_FILENO, str, len);
70+
MP_THREAD_GIL_ENTER();
71+
if (ret == -1 && errno == EINTR) {
72+
mp_handle_pending(true);
73+
continue;
74+
}
75+
}
7076
mp_uos_dupterm_tx_strn(str, len);
71-
(void)dummy;
7277
}
7378

7479
const mp_print_t mp_stderr_print = {NULL, stderr_print_strn};

0 commit comments

Comments
 (0)
0