From 6250ec1191ba925412c2e31d6b4a163ce63895ba Mon Sep 17 00:00:00 2001 From: Nick Peng Date: Sun, 26 Jun 2022 18:38:46 +0800 Subject: [PATCH] fix deadlock issue. avoid calling c library functions after vfork. --- tlog.c | 83 +++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 56 insertions(+), 27 deletions(-) diff --git a/tlog.c b/tlog.c index de897f2..d227149 100644 --- a/tlog.c +++ b/tlog.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -45,6 +46,14 @@ #define TLOG_SEGMENT_MAGIC 0xFF446154 +struct linux_dirent64 { + unsigned long long d_ino; + long long d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + struct tlog_log { char *buff; int buffsize; @@ -508,7 +517,7 @@ static int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, v buff[len - 1] = '\0'; buff[len - 2] = '\n'; buff[len - 3] = '.'; - buff[len - 5] = '.'; + buff[len - 4] = '.'; buff[len - 5] = '.'; } @@ -922,47 +931,67 @@ static void _tlog_close_all_fd_by_res(void) } } +static int _tlog_str_to_int(const char *str) +{ + int num = 0; + + while (*str >= '0' && *str <= '9') { + num = num * 10 + (*str - '0'); + ++str; + } + + if (*str) { + return -1; + } + + return num; +} + static void _tlog_close_all_fd(void) { - char path_name[PATH_MAX]; - DIR *dir = NULL; - struct dirent *ent; +#if defined(__linux__) int dir_fd = -1; - snprintf(path_name, sizeof(path_name), "/proc/self/fd/"); - dir = opendir(path_name); - if (dir == NULL) { + dir_fd = open("/proc/self/fd/", O_RDONLY | O_DIRECTORY); + if (dir_fd < 0) { goto errout; } - dir_fd = dirfd(dir); + char buffer[sizeof(struct linux_dirent64)]; + int bytes; + while ((bytes = syscall(SYS_getdents64, dir_fd, + (struct linux_dirent64 *)buffer, + sizeof(buffer))) + > 0) { + struct linux_dirent64 *entry; + int offset; - while ((ent = readdir(dir)) != NULL) { - int fd = atoi(ent->d_name); - if (fd < 0 || dir_fd == fd) { - continue; - } - switch (fd) { - case STDIN_FILENO: - case STDOUT_FILENO: - case STDERR_FILENO: - continue; - break; - default: - break; - } + for (offset = 0; offset < bytes; offset += entry->d_reclen) { + int fd; + entry = (struct linux_dirent64 *)(buffer + offset); + if ((fd = _tlog_str_to_int(entry->d_name)) < 0) { + continue; + } - close(fd); + if (fd == dir_fd || fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) { + continue; + } + close(fd); + } } - closedir(dir); + close(dir_fd); + + if (bytes < 0) { + goto errout; + } return; errout: - if (dir) { - closedir(dir); + if (dir_fd > 0) { + close(dir_fd); } - +#endif _tlog_close_all_fd_by_res(); return; }