commit 6798449c8145f9d1be8e4d32c362b9bbfa77ca4f
parent b1958060de24825479d759637e48b944c491d6dc
Author: quantumish <freifeld.david@gmail.com>
Date: Sun, 14 May 2023 13:13:39 -0700
Profiling additions
Diffstat:
| M | Dockerfile | | | 5 | +++-- |
| M | http.c | | | 139 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
2 files changed, 75 insertions(+), 69 deletions(-)
diff --git a/Dockerfile b/Dockerfile
@@ -1,8 +1,9 @@
FROM ubuntu:latest
RUN apt-get update
-# RUN apt-get install -y zlib1g
-# RUN apt-get install -y zlib1g-dev
+RUN apt-get install -y zlib1g
+RUN apt-get install -y libunwind-dev
+RUN apt-get install -y zlib1g-dev
WORKDIR /root
COPY public public
diff --git a/http.c b/http.c
@@ -17,6 +17,8 @@
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <sys/fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
@@ -120,7 +122,7 @@ response_t serve_file(request_t* req) {
}
}
}
- if (!ok) return serve_error(NotAcceptable);
+ /* if (!ok) return serve_error(NotAcceptable); */
#ifndef __APPLE__
char datebuf[64];
@@ -136,36 +138,40 @@ response_t serve_file(request_t* req) {
// TODO actually respect requests
// TODO list dirs
-response_t make_response (request_t* req, channel_t* chan) {
+response_t make_response (request_t* req, int pfd) {
if (req_parse(req) < 0) {
log_error("Failed to parse incoming request.");
return serve_error(BadRequest);
}
if (hashmap_get(&req->headers, "Profile") != 0x0) {
+ log_debug("Got header");
int profile = true;
- channel_push(chan, &profile);
- ptrace(PTRACE_TRACEME, NULL);
- /* usleep(10000); */
+ if (ptrace(PTRACE_TRACEME, NULL) < 0) {
+ log_error("PTRACE_TRACME failed with err %d", errno);
+ }
+ if (write(pfd, "profile", 8) != 8) {
+ log_error("write err");
+ }
+ usleep(100);
}
log_info("Got request %s %s", method_name(req->method), req->path);
- char* mapped_path = hashmap_get(&path_redirs, req->path);
- if (mapped_path != NULL) {
- strcpy(req->path, mapped_path);
- }
-
+ char* mapped_path = hashmap_get(&path_redirs, req->path);
+ if (mapped_path != NULL) {
+ strcpy(req->path, mapped_path);
+ }
+
if (!shitvec_check(&paths, req->path, (sv_cmp_t)strcmp)) {
return serve_error(NotFound);
}
-
+
+ log_debug("method = %d", req->method);
switch (req->method) {
- case GET: return serve_file(req); break;
+ case GET: return serve_file(req);
default: return serve_error(MethodNotAllowed);
- }
-
- return serve_error(InternalServerError); // should be unreachable?
+ }
}
double diff_timespec(const struct timespec *time1, const struct timespec *time0) {
@@ -173,23 +179,9 @@ double diff_timespec(const struct timespec *time1, const struct timespec *time0)
+ (time1->tv_nsec - time0->tv_nsec) / 1000000000.0;
}
-struct handle_conn_ctxt {
- int ns;
- channel_t* chan;
-};
-
-void* handle_conn(void* ctxt) {
- channel_t* chan = ((struct handle_conn_ctxt *)ctxt)->chan;
- int ns = ((struct handle_conn_ctxt *)ctxt)->ns;
-
- pid_t tid = gettid();
- log_debug("my tid %d", tid);
- channel_push(chan, &tid);
-
+void* handle_conn(int ns, int pfd) {
char msgbuf[1024] = {0};
while(true) {
- tid = gettid();
- log_debug("my tid %d", tid);
struct timespec before, after, tdiff;
if (recv(ns, msgbuf, 1024, 0) == 0) {
log_info("Closing connection.");
@@ -199,11 +191,11 @@ void* handle_conn(void* ctxt) {
if (msgbuf[0] != 0) {
request_t req = req_new(msgbuf, 1024);
- response_t r = make_response(&req, chan);
+ response_t r = make_response(&req, pfd);
send(ns, r.content, r.sz, 0);
free(r.content);
-
- clock_gettime(CLOCK_MONOTONIC, &after);
+ write(pfd, "stop", 5);
+ clock_gettime(CLOCK_MONOTONIC, &after);
log_info("Handled request in %f sec", diff_timespec(&after, &before));
req_free(&req);
}
@@ -232,25 +224,28 @@ int list_files_sv(shitvec_t* sv, char* base) {
channel_t listen_chan;
-void* listen_for_conns(void* ctxt) {
- int s = *(int*)ctxt;
- int namelen;
- struct sockaddr_in client;
- while (true) {
- listen(s, 1);
- int ns = accept(s, (struct sockaddr*)&client, (socklen_t*)&namelen);
- log_info("Handling connection from %s", inet_ntoa(client.sin_addr));
- channel_push(&listen_chan, &ns);
- }
-}
+/* void* listen_for_conns(void* ctxt) { */
+/* int s = *(int*)ctxt; */
+/* int namelen; */
+/* struct sockaddr_in client; */
+/* while (true) { */
+/* listen(s, 1); */
+/* int ns = accept(s, (struct sockaddr*)&client, (socklen_t*)&namelen); */
+/* log_info("Handling connection from %s", inet_ntoa(client.sin_addr)); */
+/* channel_push(&listen_chan, &ns); */
+/* } */
+/* } */
#define MAX_SYMLEN 128
int profile(pid_t tid) {
errno = 0;
+ log_debug("Tracing %d", tid);
if (ptrace(PTRACE_ATTACH, tid) < 0) {
log_error("ptrace() fail, errno %d", errno);
- }
+ }
+ kill(tid, SIGSTOP);
+ waitpid(tid, NULL, 0);
void* ui = _UPT_create(tid);
if (!ui) return -1;
unw_cursor_t c;
@@ -264,7 +259,10 @@ int profile(pid_t tid) {
} while(unw_step(&c) > 0);
_UPT_resume(as, &c, ui);
_UPT_destroy(ui);
- ptrace(PTRACE_CONT, tid);
+ kill(tid, SIGSTOP);
+ printf("waiting\n");
+ waitpid(tid, NULL, 0);
+ ptrace(PTRACE_DETACH, tid, NULL, NULL);
return 0;
}
@@ -302,31 +300,38 @@ int main() {
listen_chan = channel_new(sizeof(int));
- pthread_t lthread;
- pthread_create(&lthread, NULL, listen_for_conns, &s);
-
- shitvec_t channels = shitvec_new(sizeof(struct thread_comm));
+ /* pthread_t lthread; */
+ /* pthread_create(&lthread, NULL, listen_for_conns, &s); */
+ int namelen;
+ struct sockaddr_in client;
+
int* ns;
- pid_t* tid;
+ pid_t pid;
+
while (true) {
- if ((ns = channel_try_recv(&listen_chan))) {
- channel_t chan = channel_new(sizeof(pid_t));
- shitvec_push(&channels, &chan);
- channel_t* chanp = shitvec_last(&channels);
- struct handle_conn_ctxt ctxt = { .chan = chanp, .ns = *ns };
- pthread_t thread;
- pthread_create(&thread, NULL, handle_conn, &ctxt);
+ listen(s, 1);
+ int ns = accept(s, (struct sockaddr*)&client, (socklen_t*)&namelen);
+ log_info("Got connection");
+
+ int pfds[2];
+ pipe(pfds);
+
+ pid = fork();
+ if (pid == 0) {
+ handle_conn(ns, pfds[1]);
+ exit(0);
+ } else {
+ /* char msg[8] = {0}; */
+ /* read(pfds[0], &msg, 8); */
+ /* int retval = fcntl(pfds[0], F_SETFL, fcntl(pfds[0], F_GETFL) | O_NONBLOCK); */
+
+ /* while(true) { */
+ /* profile(pid); */
+ /* usleep(10); */
+ /* if (read(pfds[0], &msg, 5) == 5 && strcmp(msg, "stop") == 0) break; */
+ /* } */
}
- for (size_t i = 0; i < channels.vec_sz; i++) {
- struct thread_comm* comm = shitvec_get(&channels, i);
- if ((tid = channel_try_recv(&comm->chan))) {
- for (int j = 0; j < 10; j++) {
- profile(*tid);
- usleep(10);
- } /* else comm->tid = *tid; */
- }
- }
}
}