Skip to content

Commit 6250ec1

Browse files
committed
fix deadlock issue. avoid calling c library functions after vfork.
1 parent 491f605 commit 6250ec1

File tree

1 file changed

+56
-27
lines changed

1 file changed

+56
-27
lines changed

tlog.c

+56-27
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <string.h>
2020
#include <sys/resource.h>
2121
#include <sys/stat.h>
22+
#include <sys/syscall.h>
2223
#include <sys/time.h>
2324
#include <sys/types.h>
2425
#include <sys/wait.h>
@@ -45,6 +46,14 @@
4546

4647
#define TLOG_SEGMENT_MAGIC 0xFF446154
4748

49+
struct linux_dirent64 {
50+
unsigned long long d_ino;
51+
long long d_off;
52+
unsigned short d_reclen;
53+
unsigned char d_type;
54+
char d_name[256];
55+
};
56+
4857
struct tlog_log {
4958
char *buff;
5059
int buffsize;
@@ -508,7 +517,7 @@ static int _tlog_vprintf(struct tlog_log *log, vprint_callback print_callback, v
508517
buff[len - 1] = '\0';
509518
buff[len - 2] = '\n';
510519
buff[len - 3] = '.';
511-
buff[len - 5] = '.';
520+
buff[len - 4] = '.';
512521
buff[len - 5] = '.';
513522
}
514523

@@ -922,47 +931,67 @@ static void _tlog_close_all_fd_by_res(void)
922931
}
923932
}
924933

934+
static int _tlog_str_to_int(const char *str)
935+
{
936+
int num = 0;
937+
938+
while (*str >= '0' && *str <= '9') {
939+
num = num * 10 + (*str - '0');
940+
++str;
941+
}
942+
943+
if (*str) {
944+
return -1;
945+
}
946+
947+
return num;
948+
}
949+
925950
static void _tlog_close_all_fd(void)
926951
{
927-
char path_name[PATH_MAX];
928-
DIR *dir = NULL;
929-
struct dirent *ent;
952+
#if defined(__linux__)
930953
int dir_fd = -1;
931954

932-
snprintf(path_name, sizeof(path_name), "/proc/self/fd/");
933-
dir = opendir(path_name);
934-
if (dir == NULL) {
955+
dir_fd = open("/proc/self/fd/", O_RDONLY | O_DIRECTORY);
956+
if (dir_fd < 0) {
935957
goto errout;
936958
}
937959

938-
dir_fd = dirfd(dir);
960+
char buffer[sizeof(struct linux_dirent64)];
961+
int bytes;
962+
while ((bytes = syscall(SYS_getdents64, dir_fd,
963+
(struct linux_dirent64 *)buffer,
964+
sizeof(buffer)))
965+
> 0) {
966+
struct linux_dirent64 *entry;
967+
int offset;
939968

940-
while ((ent = readdir(dir)) != NULL) {
941-
int fd = atoi(ent->d_name);
942-
if (fd < 0 || dir_fd == fd) {
943-
continue;
944-
}
945-
switch (fd) {
946-
case STDIN_FILENO:
947-
case STDOUT_FILENO:
948-
case STDERR_FILENO:
949-
continue;
950-
break;
951-
default:
952-
break;
953-
}
969+
for (offset = 0; offset < bytes; offset += entry->d_reclen) {
970+
int fd;
971+
entry = (struct linux_dirent64 *)(buffer + offset);
972+
if ((fd = _tlog_str_to_int(entry->d_name)) < 0) {
973+
continue;
974+
}
954975

955-
close(fd);
976+
if (fd == dir_fd || fd == STDIN_FILENO || fd == STDOUT_FILENO || fd == STDERR_FILENO) {
977+
continue;
978+
}
979+
close(fd);
980+
}
956981
}
957982

958-
closedir(dir);
983+
close(dir_fd);
984+
985+
if (bytes < 0) {
986+
goto errout;
987+
}
959988

960989
return;
961990
errout:
962-
if (dir) {
963-
closedir(dir);
991+
if (dir_fd > 0) {
992+
close(dir_fd);
964993
}
965-
994+
#endif
966995
_tlog_close_all_fd_by_res();
967996
return;
968997
}

0 commit comments

Comments
 (0)