Re: [PATCH] ring-buffer: Fix polling on trace_pipe

Steven Rostedt
2014-07-15T19:46:28Z

[-- Attachment #1: Type: text/plain, Size: 503 bytes --]

On Thu, 10 Jul 2014 15:20:30 -0700
Martin Lau <kafai@fb.com> wrote:

> Hi Steve,
>
> Do you have a chance to give it another try?
>

OK, I finally got around to testing it. Yep I see your point. Do you
think it should go to 3.16 and stable? I can add it to my next git pull
request.

Also, I modified your test such that it wouldn't hang on failure, but
detects that it hung and returns a exit value to add this to my
testing. That is, it exits with zero on success and non zero on failure.

-- Steve

[-- Attachment #2: ftrace-test-epoll-kafai-2.c --]
[-- Type: text/x-c++src, Size: 2759 bytes --]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <signal.h>
#include <errno.h>

static const char * debugfs_list[] = {
"/debug/tracing",
"/sys/kernel/debug/tracing",
"/d/tracing",
NULL,
};

static const char *debugfs;
static int markfd;
static int trace_pipe_fd;

static void alog(const char *name, int ret)
{
printf("%d: %s: %d\n", getpid(), name, ret);
}

static const char *find_debugfs(void)
{
struct stat st;
int i;
int r;

for (i = 0; debugfs_list[i]; i++) {
r = stat(debugfs_list[i], &st);
if (r < 0)
continue;
if (S_ISDIR(st.st_mode))
return debugfs_list[i];
}
return NULL;
}

static char * make_path(const char *file)
{
char *path;
int size;

size = strlen(debugfs) + strlen(file) + 2;
path = malloc(size);
if (!path) {
perror("malloc");
exit(-1);
}
sprintf(path, "%s/%s", debugfs, file);
return path;
}

static void mark_write(const char *str)
{
int ret;
ret = write(markfd, str, strlen(str));
alog("write(markfd)", ret);
}

static void read_trace_pipe(void)
{
char buf[1024];
int r;

while ((r = read(trace_pipe_fd, buf, 1024)) > 0)
printf("%.*s", r, buf);
}

int main (int argc, char **argv)
{
struct epoll_event ee;
char *marker;
char *pipe;
int efd;
int ret;
pid_t dwrt_pid;

debugfs = find_debugfs();
if (!debugfs) {
fprintf(stderr, "Could not find debugfs\n");
exit(-1);
}

marker = make_path("trace_marker");
pipe = make_path("trace_pipe");

markfd = open(marker, O_WRONLY);
if (markfd < 0) {
perror("marker");
exit(-1);
}
trace_pipe_fd = open(pipe, O_RDONLY|O_NONBLOCK);
if (trace_pipe_fd < 0) {
perror("trace_pipe");
exit(-1);
}

efd = epoll_create(1);
if (efd < 0) {
perror("epoll_create");
exit(-1);
}

mark_write("some data");
memset(&ee, 0, sizeof(ee));
ee.events = EPOLLIN;
ret = epoll_ctl(efd, EPOLL_CTL_ADD, trace_pipe_fd, &ee);
if (ret < 0) {
perror("epoll_ctl");
exit(-1);
}
alog("waiting data......", 0);
ret = epoll_wait(efd, &ee, 1, -1);
alog("epoll_wait()", ret);
read_trace_pipe();
dwrt_pid = fork();
assert(dwrt_pid != -1);
if (dwrt_pid > 0) {
int status;
sleep(10);
mark_write("more data");
sleep(10);
ret = waitpid(dwrt_pid, &status, WNOHANG);
if (ret != dwrt_pid) {
alog("Poll never finished!", 0);
kill(dwrt_pid, 9);
exit(-1);
}
if (WEXITSTATUS(status) != 0) {
alog("Something failed on polling!",
WEXITSTATUS(status));
exit(-1);
}
} else {
alog("waiting form more data......", 0);
ret = epoll_wait(efd, &ee, 1, -1);
alog("epoll_wait()", ret);
read_trace_pipe();
if (ret < 0)
exit(errno);
}
exit (0);
}