Merge branch 'strace-leaks' of BenBE/htop

Closes #262
This commit is contained in:
Daniel Lange 2020-10-18 19:43:24 +02:00
commit 8534dcb87c
2 changed files with 64 additions and 29 deletions

View File

@ -44,11 +44,10 @@ const InfoScreenClass TraceScreen_class = {
}; };
TraceScreen* TraceScreen_new(Process* process) { TraceScreen* TraceScreen_new(Process* process) {
TraceScreen* this = xMalloc(sizeof(TraceScreen)); // This initializes all TraceScreen variables to "false" so only default = true ones need to be set below
TraceScreen* this = xCalloc(1, sizeof(TraceScreen));
Object_setClass(this, Class(TraceScreen)); Object_setClass(this, Class(TraceScreen));
this->tracing = true; this->tracing = true;
this->contLine = false;
this->follow = false;
FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents); FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents);
CRT_disableDelay(); CRT_disableDelay();
return (TraceScreen*) InfoScreen_init(&this->super, process, fuBar, LINES-2, ""); return (TraceScreen*) InfoScreen_init(&this->super, process, fuBar, LINES-2, "");
@ -59,10 +58,11 @@ void TraceScreen_delete(Object* cast) {
if (this->child > 0) { if (this->child > 0) {
kill(this->child, SIGTERM); kill(this->child, SIGTERM);
waitpid(this->child, NULL, 0); waitpid(this->child, NULL, 0);
fclose(this->strace);
} }
if (this->strace)
fclose(this->strace);
CRT_enableDelay(); CRT_enableDelay();
free(InfoScreen_done((InfoScreen*)cast)); free(InfoScreen_done((InfoScreen*)this));
} }
void TraceScreen_draw(InfoScreen* this) { void TraceScreen_draw(InfoScreen* this) {
@ -74,43 +74,75 @@ void TraceScreen_draw(InfoScreen* this) {
} }
bool TraceScreen_forkTracer(TraceScreen* this) { bool TraceScreen_forkTracer(TraceScreen* this) {
int error = pipe(this->fdpair); int fdpair[2] = {0, 0};
if (error == -1) return false;
this->child = fork(); if (pipe(fdpair) == -1)
if (this->child == -1) return false; return false;
if (this->child == 0) {
if(fcntl(fdpair[0], F_SETFL, O_NONBLOCK) < 0)
goto err;
if(fcntl(fdpair[1], F_SETFL, O_NONBLOCK) < 0)
goto err;
pid_t child = fork();
if (child == -1)
goto err;
if (child == 0) {
close(fdpair[0]);
dup2(fdpair[1], STDOUT_FILENO);
dup2(fdpair[1], STDERR_FILENO);
close(fdpair[1]);
CRT_dropPrivileges(); CRT_dropPrivileges();
dup2(this->fdpair[1], STDERR_FILENO);
int ok = fcntl(this->fdpair[1], F_SETFL, O_NONBLOCK);
if (ok != -1) {
char buffer[32] = {0}; char buffer[32] = {0};
xSnprintf(buffer, sizeof(buffer), "%d", this->super.process->pid); xSnprintf(buffer, sizeof(buffer), "%d", this->super.process->pid);
execlp("strace", "strace", "-T", "-tt", "-s", "512", "-p", buffer, NULL); execlp("strace", "strace", "-T", "-tt", "-s", "512", "-p", buffer, NULL);
}
// Should never reach here, unless execlp fails ...
const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH."; const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH.";
ssize_t written = write(this->fdpair[1], message, strlen(message)); ssize_t written = write(STDERR_FILENO, message, strlen(message));
(void) written; (void) written;
exit(1);
exit(127);
} }
int ok = fcntl(this->fdpair[0], F_SETFL, O_NONBLOCK);
if (ok == -1) return false; FILE* fd = fdopen(fdpair[0], "r");
this->strace = fdopen(this->fdpair[0], "r"); if (!fd)
this->fd_strace = fileno(this->strace); goto err;
close(fdpair[1]);
this->child = child;
this->strace = fd;
return true; return true;
err:
close(fdpair[1]);
close(fdpair[0]);
return false;
} }
void TraceScreen_updateTrace(InfoScreen* super) { void TraceScreen_updateTrace(InfoScreen* super) {
TraceScreen* this = (TraceScreen*) super; TraceScreen* this = (TraceScreen*) super;
char buffer[1025]; char buffer[1025];
int fd_strace = fileno(this->strace);
assert(fd_strace != -1);
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
// FD_SET(STDIN_FILENO, &fds); // FD_SET(STDIN_FILENO, &fds);
FD_SET(this->fd_strace, &fds); FD_SET(fd_strace, &fds);
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_usec = 500; tv.tv_sec = 0; tv.tv_usec = 500;
int ready = select(this->fd_strace+1, &fds, NULL, NULL, &tv); int ready = select(fd_strace+1, &fds, NULL, NULL, &tv);
size_t nread = 0; size_t nread = 0;
if (ready > 0 && FD_ISSET(this->fd_strace, &fds)) if (ready > 0 && FD_ISSET(fd_strace, &fds))
nread = fread(buffer, 1, sizeof(buffer) - 1, this->strace); nread = fread(buffer, 1, sizeof(buffer) - 1, this->strace);
if (nread && this->tracing) { if (nread && this->tracing) {
const char* line = buffer; const char* line = buffer;

View File

@ -7,15 +7,18 @@ Released under the GNU GPLv2, see the COPYING file
in the source distribution for its full text. in the source distribution for its full text.
*/ */
#include <stdbool.h>
#include <stdio.h>
#include <sys/types.h>
#include "InfoScreen.h" #include "InfoScreen.h"
typedef struct TraceScreen_ { typedef struct TraceScreen_ {
InfoScreen super; InfoScreen super;
bool tracing; bool tracing;
int fdpair[2]; pid_t child;
int child;
FILE* strace; FILE* strace;
int fd_strace;
bool contLine; bool contLine;
bool follow; bool follow;
} TraceScreen; } TraceScreen;