Use an interrupt-safe close()

This commit is contained in:
Kovid Goyal 2019-07-05 14:39:07 +05:30
parent 547132131a
commit c848c3ee0d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 25 additions and 23 deletions

View File

@ -746,7 +746,7 @@ thread_write(void *x) {
if (pos < data->sz) { if (pos < data->sz) {
log_error("Failed to write all data to STDIN of child process with error: %s", strerror(errno)); log_error("Failed to write all data to STDIN of child process with error: %s", strerror(errno));
} }
close(data->fd); safe_close(data->fd);
free_twd(data); free_twd(data);
return 0; return 0;
} }
@ -763,7 +763,7 @@ cm_thread_write(PyObject UNUSED *self, PyObject *args) {
data->fd = fd; data->fd = fd;
memcpy(data->buf, buf, data->sz); memcpy(data->buf, buf, data->sz);
int ret = pthread_create(&thread, NULL, thread_write, data); int ret = pthread_create(&thread, NULL, thread_write, data);
if (ret != 0) { close(fd); free_twd(data); return PyErr_SetFromErrno(PyExc_OSError); } if (ret != 0) { safe_close(fd); free_twd(data); return PyErr_SetFromErrno(PyExc_OSError); }
pthread_detach(thread); pthread_detach(thread);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@ -977,7 +977,7 @@ hangup(pid_t pid) {
static inline void static inline void
cleanup_child(ssize_t i) { cleanup_child(ssize_t i) {
close(children[i].fd); safe_close(children[i].fd);
hangup(children[i].pid); hangup(children[i].pid);
} }
@ -1268,7 +1268,7 @@ typedef struct {
static TalkData talk_data = {0}; static TalkData talk_data = {0};
typedef struct pollfd PollFD; typedef struct pollfd PollFD;
#define PEER_LIMIT 256 #define PEER_LIMIT 256
#define nuke_socket(s) { shutdown(s, SHUT_RDWR); close(s); } #define nuke_socket(s) { shutdown(s, SHUT_RDWR); safe_close(s); }
static inline bool static inline bool
accept_peer(int listen_fd, bool shutting_down) { accept_peer(int listen_fd, bool shutting_down) {
@ -1389,7 +1389,7 @@ prune_finished_writes(void) {
PeerWriteData *wd = talk_data.writes + i; PeerWriteData *wd = talk_data.writes + i;
if (wd->finished) { if (wd->finished) {
remove_poll_fd(wd->fd); remove_poll_fd(wd->fd);
shutdown(wd->fd, SHUT_WR); close(wd->fd); shutdown(wd->fd, SHUT_WR); safe_close(wd->fd);
free(wd->data); free(wd->data);
ssize_t num_to_right = talk_data.num_writes - 1 - i; ssize_t num_to_right = talk_data.num_writes - 1 - i;
if (num_to_right > 0) memmove(talk_data.writes + i, talk_data.writes + i + 1, num_to_right * sizeof(PeerWriteData)); if (num_to_right > 0) memmove(talk_data.writes + i, talk_data.writes + i + 1, num_to_right * sizeof(PeerWriteData));
@ -1487,8 +1487,8 @@ add_peer_writer(int fd, const char* msg, size_t msg_sz) {
static void static void
send_response(int fd, const char *msg, size_t msg_sz) { send_response(int fd, const char *msg, size_t msg_sz) {
if (msg == NULL) { shutdown(fd, SHUT_WR); close(fd); return; } if (msg == NULL) { shutdown(fd, SHUT_WR); safe_close(fd); return; }
if (!add_peer_writer(fd, msg, msg_sz)) { shutdown(fd, SHUT_WR); close(fd); } if (!add_peer_writer(fd, msg, msg_sz)) { shutdown(fd, SHUT_WR); safe_close(fd); }
else wakeup_talk_loop(false); else wakeup_talk_loop(false);
} }

View File

@ -91,28 +91,28 @@ spawn(PyObject *self UNUSED, PyObject *args) {
// On BSD open() does not establish the controlling terminal // On BSD open() does not establish the controlling terminal
if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY"); if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY");
#endif #endif
close(tfd); safe_close(tfd);
// Redirect stdin/stdout/stderr to the pty // Redirect stdin/stdout/stderr to the pty
if (dup2(slave, 1) == -1) exit_on_err("dup2() failed for fd number 1"); if (dup2(slave, 1) == -1) exit_on_err("dup2() failed for fd number 1");
if (dup2(slave, 2) == -1) exit_on_err("dup2() failed for fd number 2"); if (dup2(slave, 2) == -1) exit_on_err("dup2() failed for fd number 2");
if (stdin_read_fd > -1) { if (stdin_read_fd > -1) {
if (dup2(stdin_read_fd, 0) == -1) exit_on_err("dup2() failed for fd number 0"); if (dup2(stdin_read_fd, 0) == -1) exit_on_err("dup2() failed for fd number 0");
close(stdin_read_fd); safe_close(stdin_read_fd);
close(stdin_write_fd); safe_close(stdin_write_fd);
} else { } else {
if (dup2(slave, 0) == -1) exit_on_err("dup2() failed for fd number 0"); if (dup2(slave, 0) == -1) exit_on_err("dup2() failed for fd number 0");
} }
close(slave); safe_close(slave);
close(master); safe_close(master);
// Wait for READY_SIGNAL which indicates kitty has setup the screen object // Wait for READY_SIGNAL which indicates kitty has setup the screen object
close(ready_write_fd); safe_close(ready_write_fd);
wait_for_terminal_ready(ready_read_fd); wait_for_terminal_ready(ready_read_fd);
close(ready_read_fd); safe_close(ready_read_fd);
// Close any extra fds inherited from parent // Close any extra fds inherited from parent
for (int c = 3; c < 201; c++) close(c); for (int c = 3; c < 201; c++) safe_close(c);
environ = env; environ = env;
// for some reason SIGPIPE is set to SIG_IGN, so reset it, needed by bash, // for some reason SIGPIPE is set to SIG_IGN, so reset it, needed by bash,

View File

@ -179,7 +179,7 @@ close_tty(PyObject *self UNUSED, PyObject *args) {
TTY_ARGS TTY_ARGS
tcsetattr(fd, TCSAFLUSH, termios_p); // deliberately ignore failure tcsetattr(fd, TCSAFLUSH, termios_p); // deliberately ignore failure
free(termios_p); free(termios_p);
close(fd); safe_close(fd);
Py_RETURN_NONE; Py_RETURN_NONE;
} }

View File

@ -311,3 +311,5 @@ void play_canberra_sound(const char *which_sound, const char *event_id);
#endif #endif
SPRITE_MAP_HANDLE alloc_sprite_map(unsigned int, unsigned int); SPRITE_MAP_HANDLE alloc_sprite_map(unsigned int, unsigned int);
SPRITE_MAP_HANDLE free_sprite_map(SPRITE_MAP_HANDLE); SPRITE_MAP_HANDLE free_sprite_map(SPRITE_MAP_HANDLE);
static inline void safe_close(int fd) { while(close(fd) != 0 && errno == EINTR); }

View File

@ -359,7 +359,7 @@ handle_add_command(GraphicsManager *self, const GraphicsCommand *g, const uint8_
else fd = open(fname, O_CLOEXEC | O_RDONLY); else fd = open(fname, O_CLOEXEC | O_RDONLY);
if (fd == -1) ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno)); if (fd == -1) ABRT(EBADF, "Failed to open file %s for graphics transmission with error: [%d] %s", fname, errno, strerror(errno));
img->data_loaded = mmap_img_file(self, img, fd, g->data_sz, g->data_offset); img->data_loaded = mmap_img_file(self, img, fd, g->data_sz, g->data_offset);
close(fd); safe_close(fd);
if (tt == 't') { if (tt == 't') {
if (global_state.boss) { call_boss(safe_delete_temp_file, "s", fname); } if (global_state.boss) { call_boss(safe_delete_temp_file, "s", fname); }
else unlink(fname); else unlink(fname);
@ -839,12 +839,12 @@ W(shm_write) {
int fd = shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR); int fd = shm_open(name, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd == -1) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; } if (fd == -1) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; }
int ret = ftruncate(fd, sz); int ret = ftruncate(fd, sz);
if (ret != 0) { close(fd); PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; } if (ret != 0) { safe_close(fd); PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; }
void *addr = mmap(0, sz, PROT_WRITE, MAP_SHARED, fd, 0); void *addr = mmap(0, sz, PROT_WRITE, MAP_SHARED, fd, 0);
if (addr == MAP_FAILED) { close(fd); PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; } if (addr == MAP_FAILED) { safe_close(fd); PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; }
memcpy(addr, data, sz); memcpy(addr, data, sz);
if (munmap(addr, sz) != 0) { close(fd); PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; } if (munmap(addr, sz) != 0) { safe_close(fd); PyErr_SetFromErrnoWithFilename(PyExc_OSError, name); return NULL; }
close(fd); safe_close(fd);
Py_RETURN_NONE; Py_RETURN_NONE;
} }

View File

@ -43,7 +43,7 @@ handle_signal(int sig_num) {
void void
free_loop_data(LoopData *ld) { free_loop_data(LoopData *ld) {
#define CLOSE(which, idx) if (ld->which[idx] > -1) close(ld->which[idx]); ld->which[idx] = -1; #define CLOSE(which, idx) if (ld->which[idx] > -1) safe_close(ld->which[idx]); ld->which[idx] = -1;
CLOSE(wakeup_fds, 0); CLOSE(wakeup_fds, 1); CLOSE(wakeup_fds, 0); CLOSE(wakeup_fds, 1);
#ifndef HAS_SIGNAL_FD #ifndef HAS_SIGNAL_FD
CLOSE(signal_fds, 0); CLOSE(signal_fds, 1); CLOSE(signal_fds, 0); CLOSE(signal_fds, 1);
@ -51,7 +51,7 @@ free_loop_data(LoopData *ld) {
#undef CLOSE #undef CLOSE
if (ld->signal_read_fd) { if (ld->signal_read_fd) {
#ifdef HAS_SIGNAL_FD #ifdef HAS_SIGNAL_FD
close(ld->signal_read_fd); safe_close(ld->signal_read_fd);
SIGNAL_SET SIGNAL_SET
sigprocmask(SIG_UNBLOCK, &signals, NULL); sigprocmask(SIG_UNBLOCK, &signals, NULL);
#else #else