Crashlog: Use a temp file instead of a pipe to read from gdb/lldb

This commit is contained in:
Jonathan G Rennison
2022-05-31 22:01:52 +01:00
parent 4a0fa0cc75
commit d83f0d0cda
2 changed files with 103 additions and 25 deletions

View File

@@ -48,23 +48,35 @@
#define MAX_STACK_FRAMES 64 #define MAX_STACK_FRAMES 64
#if !defined(WITHOUT_DBG_LLDB) #if !defined(WITHOUT_DBG_LLDB)
static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, const char *last) static bool ExecReadStdoutThroughFile(const char *file, char *const *args, char *&buffer, const char *last)
{ {
int null_fd = open("/dev/null", O_RDWR); int null_fd = open("/dev/null", O_RDWR);
if (null_fd == -1) return false; if (null_fd == -1) return false;
int pipefd[2]; char name[MAX_PATH];
if (pipe(pipefd) == -1) return false; extern std::string _personal_dir;
seprintf(name, lastof(name), "%sopenttd-tmp-XXXXXX", _personal_dir.c_str());
int fd = mkstemp(name);
if (fd == -1) {
close(null_fd);
return false;
}
/* Unlink file but leave fd open until finished with */
unlink(name);
int pid = fork(); int pid = fork();
if (pid < 0) return false; if (pid < 0) {
close(null_fd);
close(fd);
return false;
}
if (pid == 0) { if (pid == 0) {
/* child */ /* child */
close(pipefd[0]); /* Close unused read end */ dup2(fd, STDOUT_FILENO);
dup2(pipefd[1], STDOUT_FILENO); close(fd);
close(pipefd[1]);
dup2(null_fd, STDERR_FILENO); dup2(null_fd, STDERR_FILENO);
dup2(null_fd, STDIN_FILENO); dup2(null_fd, STDIN_FILENO);
close(null_fd); close(null_fd);
@@ -76,10 +88,18 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
/* parent */ /* parent */
close(null_fd); close(null_fd);
close(pipefd[1]); /* Close unused write end */
int status;
int wait_ret = waitpid(pid, &status, 0);
if (wait_ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
/* command did not appear to run successfully */
close(fd);
return false;
} else {
/* command executed successfully */
lseek(fd, 0, SEEK_SET);
while (buffer < last) { while (buffer < last) {
ssize_t res = read(pipefd[0], buffer, last - buffer); ssize_t res = read(fd, buffer, last - buffer);
if (res < 0) { if (res < 0) {
if (errno == EINTR) continue; if (errno == EINTR) continue;
break; break;
@@ -90,16 +110,7 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
} }
} }
buffer += seprintf(buffer, last, "\n"); buffer += seprintf(buffer, last, "\n");
close(fd);
close(pipefd[0]); /* close read end */
int status;
int wait_ret = waitpid(pid, &status, 0);
if (wait_ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
/* command did not appear to run successfully */
return false;
} else {
/* command executed successfully */
return true; return true;
} }
} }
@@ -284,7 +295,7 @@ class CrashLogOSX : public CrashLog {
} }
args.push_back(nullptr); args.push_back(nullptr);
if (!ExecReadStdout("lldb", const_cast<char* const*>(&(args[0])), buffer, last)) { if (!ExecReadStdoutThroughFile("lldb", const_cast<char* const*>(&(args[0])), buffer, last)) {
buffer = buffer_orig; buffer = buffer_orig;
} }
#endif /* !WITHOUT_DBG_LLDB */ #endif /* !WITHOUT_DBG_LLDB */

View File

@@ -128,6 +128,73 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
} }
} }
static bool ExecReadStdoutThroughFile(const char *file, char *const *args, char *&buffer, const char *last)
{
int null_fd = open("/dev/null", O_RDWR);
if (null_fd == -1) return false;
char name[MAX_PATH];
extern std::string _personal_dir;
seprintf(name, lastof(name), "%sopenttd-tmp-XXXXXX", _personal_dir.c_str());
int fd = mkstemp(name);
if (fd == -1) {
close(null_fd);
return false;
}
/* Unlink file but leave fd open until finished with */
unlink(name);
int pid = fork();
if (pid < 0) {
close(null_fd);
close(fd);
return false;
}
if (pid == 0) {
/* child */
dup2(fd, STDOUT_FILENO);
close(fd);
dup2(null_fd, STDERR_FILENO);
dup2(null_fd, STDIN_FILENO);
close(null_fd);
execvp(file, args);
exit(42);
}
/* parent */
close(null_fd);
int status;
int wait_ret = waitpid(pid, &status, 0);
if (wait_ret == -1 || !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
/* command did not appear to run successfully */
close(fd);
return false;
} else {
/* command executed successfully */
lseek(fd, 0, SEEK_SET);
while (buffer < last) {
ssize_t res = read(fd, buffer, last - buffer);
if (res < 0) {
if (errno == EINTR) continue;
break;
} else if (res == 0) {
break;
} else {
buffer += res;
}
}
buffer += seprintf(buffer, last, "\n");
close(fd);
return true;
}
}
/** /**
* Unix implementation for the crash logger. * Unix implementation for the crash logger.
*/ */
@@ -357,7 +424,7 @@ class CrashLogUnix : public CrashLog {
#endif #endif
args.push_back(nullptr); args.push_back(nullptr);
if (!ExecReadStdout("gdb", const_cast<char* const*>(&(args[0])), buffer, last)) { if (!ExecReadStdoutThroughFile("gdb", const_cast<char* const*>(&(args[0])), buffer, last)) {
buffer = buffer_orig; buffer = buffer_orig;
} }
#endif /* WITH_DBG_GDB */ #endif /* WITH_DBG_GDB */