Skip to content

Commit

Permalink
fix deadlock issue. avoid calling c library functions after vfork.
Browse files Browse the repository at this point in the history
  • Loading branch information
pymumu committed Jun 26, 2022
1 parent 491f605 commit 6250ec1
Showing 1 changed file with 56 additions and 27 deletions.
83 changes: 56 additions & 27 deletions tlog.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include <string.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
Expand All @@ -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;
Expand Down Expand Up @@ -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] = '.';
}

Expand Down Expand Up @@ -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;
}
Expand Down

0 comments on commit 6250ec1

Please sign in to comment.