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
#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);
if (null_fd == -1) return false;
int pipefd[2];
if (pipe(pipefd) == -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) return false;
if (pid < 0) {
close(null_fd);
close(fd);
return false;
}
if (pid == 0) {
/* child */
close(pipefd[0]); /* Close unused read end */
dup2(pipefd[1], STDOUT_FILENO);
close(pipefd[1]);
dup2(fd, STDOUT_FILENO);
close(fd);
dup2(null_fd, STDERR_FILENO);
dup2(null_fd, STDIN_FILENO);
close(null_fd);
@@ -76,10 +88,18 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
/* parent */
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) {
ssize_t res = read(pipefd[0], buffer, last - buffer);
ssize_t res = read(fd, buffer, last - buffer);
if (res < 0) {
if (errno == EINTR) continue;
break;
@@ -90,16 +110,7 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
}
}
buffer += seprintf(buffer, last, "\n");
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 */
close(fd);
return true;
}
}
@@ -284,7 +295,7 @@ class CrashLogOSX : public CrashLog {
}
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;
}
#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.
*/
@@ -357,7 +424,7 @@ class CrashLogUnix : public CrashLog {
#endif
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;
}
#endif /* WITH_DBG_GDB */