Crashlog: Support gdb read when /dev/null is missing
This commit is contained in:
@@ -72,16 +72,66 @@ static void LogStacktraceSigSegvHandler(int sig)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static int GetTemporaryFD()
|
||||||
|
{
|
||||||
|
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) {
|
||||||
|
/* Unlink file but leave fd open until finished with */
|
||||||
|
unlink(name);
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ExecReadNullHandler {
|
||||||
|
int fd[2] = { -1, -1 };
|
||||||
|
|
||||||
|
bool Init() {
|
||||||
|
this->fd[0] = open("/dev/null", O_RDWR);
|
||||||
|
if (this->fd[0] == -1) {
|
||||||
|
this->fd[0] = GetTemporaryFD();
|
||||||
|
if (this->fd[0] == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->fd[1] = GetTemporaryFD();
|
||||||
|
if (this->fd[1] == -1) {
|
||||||
|
this->Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this->fd[1] = this->fd[0];
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close() {
|
||||||
|
if (this->fd[0] != -1) close(this->fd[0]);
|
||||||
|
if (this->fd[1] != -1 && this->fd[0] != this->fd[1]) close(this->fd[1]);
|
||||||
|
this->fd[0] = -1;
|
||||||
|
this->fd[1] = -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, const char *last)
|
static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, const char *last)
|
||||||
{
|
{
|
||||||
int null_fd = open("/dev/null", O_RDWR);
|
ExecReadNullHandler nulls;
|
||||||
if (null_fd == -1) return false;
|
if (!nulls.Init()) return false;
|
||||||
|
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
if (pipe(pipefd) == -1) return false;
|
if (pipe(pipefd) == -1) {
|
||||||
|
nulls.Close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if (pid < 0) return false;
|
if (pid < 0) {
|
||||||
|
nulls.Close();
|
||||||
|
close(pipefd[0]);
|
||||||
|
close(pipefd[1]);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (pid == 0) {
|
if (pid == 0) {
|
||||||
/* child */
|
/* child */
|
||||||
@@ -89,9 +139,9 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
|
|||||||
close(pipefd[0]); /* Close unused read end */
|
close(pipefd[0]); /* Close unused read end */
|
||||||
dup2(pipefd[1], STDOUT_FILENO);
|
dup2(pipefd[1], STDOUT_FILENO);
|
||||||
close(pipefd[1]);
|
close(pipefd[1]);
|
||||||
dup2(null_fd, STDERR_FILENO);
|
dup2(nulls.fd[0], STDERR_FILENO);
|
||||||
dup2(null_fd, STDIN_FILENO);
|
dup2(nulls.fd[1], STDIN_FILENO);
|
||||||
close(null_fd);
|
nulls.Close();
|
||||||
|
|
||||||
execvp(file, args);
|
execvp(file, args);
|
||||||
exit(42);
|
exit(42);
|
||||||
@@ -99,7 +149,7 @@ static bool ExecReadStdout(const char *file, char *const *args, char *&buffer, c
|
|||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
|
|
||||||
close(null_fd);
|
nulls.Close();
|
||||||
close(pipefd[1]); /* Close unused write end */
|
close(pipefd[1]); /* Close unused write end */
|
||||||
|
|
||||||
while (buffer < last) {
|
while (buffer < last) {
|
||||||
@@ -130,24 +180,18 @@ 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)
|
static bool ExecReadStdoutThroughFile(const char *file, char *const *args, char *&buffer, const char *last)
|
||||||
{
|
{
|
||||||
int null_fd = open("/dev/null", O_RDWR);
|
ExecReadNullHandler nulls;
|
||||||
if (null_fd == -1) return false;
|
if (!nulls.Init()) return false;
|
||||||
|
|
||||||
char name[MAX_PATH];
|
int fd = GetTemporaryFD();
|
||||||
extern std::string _personal_dir;
|
|
||||||
seprintf(name, lastof(name), "%sopenttd-tmp-XXXXXX", _personal_dir.c_str());
|
|
||||||
int fd = mkstemp(name);
|
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
close(null_fd);
|
nulls.Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlink file but leave fd open until finished with */
|
|
||||||
unlink(name);
|
|
||||||
|
|
||||||
int pid = fork();
|
int pid = fork();
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
close(null_fd);
|
nulls.Close();
|
||||||
close(fd);
|
close(fd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -157,9 +201,9 @@ static bool ExecReadStdoutThroughFile(const char *file, char *const *args, char
|
|||||||
|
|
||||||
dup2(fd, STDOUT_FILENO);
|
dup2(fd, STDOUT_FILENO);
|
||||||
close(fd);
|
close(fd);
|
||||||
dup2(null_fd, STDERR_FILENO);
|
dup2(nulls.fd[0], STDERR_FILENO);
|
||||||
dup2(null_fd, STDIN_FILENO);
|
dup2(nulls.fd[1], STDIN_FILENO);
|
||||||
close(null_fd);
|
nulls.Close();
|
||||||
|
|
||||||
execvp(file, args);
|
execvp(file, args);
|
||||||
exit(42);
|
exit(42);
|
||||||
@@ -167,7 +211,7 @@ static bool ExecReadStdoutThroughFile(const char *file, char *const *args, char
|
|||||||
|
|
||||||
/* parent */
|
/* parent */
|
||||||
|
|
||||||
close(null_fd);
|
nulls.Close();
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
int wait_ret = waitpid(pid, &status, 0);
|
int wait_ret = waitpid(pid, &status, 0);
|
||||||
|
Reference in New Issue
Block a user