mirror of
https://github.com/RGBCube/serenity
synced 2025-05-22 17:05:10 +00:00
LibCore+rpcdump: Publish CObject graph to on-demand RPC socket
All programs that have a CEventLoop now allow local socket connections via /tmp/rpc.PID and will dump a serialized JSON array of all the live CObjects in the program onto connecting sockets. Also added a small /bin/rpcdump tool that connects to an RPC socket and produces a raw dump of the JSON that comes out.
This commit is contained in:
parent
2fa2d72761
commit
1febd59f83
3 changed files with 77 additions and 1 deletions
|
@ -1,6 +1,10 @@
|
||||||
|
#include <AK/JsonArray.h>
|
||||||
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/JsonValue.h>
|
||||||
#include <AK/Time.h>
|
#include <AK/Time.h>
|
||||||
#include <LibCore/CEvent.h>
|
#include <LibCore/CEvent.h>
|
||||||
#include <LibCore/CEventLoop.h>
|
#include <LibCore/CEventLoop.h>
|
||||||
|
#include <LibCore/CLocalSocket.h>
|
||||||
#include <LibCore/CLock.h>
|
#include <LibCore/CLock.h>
|
||||||
#include <LibCore/CNotifier.h>
|
#include <LibCore/CNotifier.h>
|
||||||
#include <LibCore/CObject.h>
|
#include <LibCore/CObject.h>
|
||||||
|
@ -25,6 +29,7 @@ HashMap<int, NonnullOwnPtr<CEventLoop::EventLoopTimer>>* CEventLoop::s_timers;
|
||||||
HashTable<CNotifier*>* CEventLoop::s_notifiers;
|
HashTable<CNotifier*>* CEventLoop::s_notifiers;
|
||||||
int CEventLoop::s_next_timer_id = 1;
|
int CEventLoop::s_next_timer_id = 1;
|
||||||
int CEventLoop::s_wake_pipe_fds[2];
|
int CEventLoop::s_wake_pipe_fds[2];
|
||||||
|
CLocalServer CEventLoop::s_rpc_server;
|
||||||
|
|
||||||
CEventLoop::CEventLoop()
|
CEventLoop::CEventLoop()
|
||||||
{
|
{
|
||||||
|
@ -39,6 +44,32 @@ CEventLoop::CEventLoop()
|
||||||
int rc = pipe2(s_wake_pipe_fds, O_CLOEXEC);
|
int rc = pipe2(s_wake_pipe_fds, O_CLOEXEC);
|
||||||
ASSERT(rc == 0);
|
ASSERT(rc == 0);
|
||||||
s_event_loop_stack->append(this);
|
s_event_loop_stack->append(this);
|
||||||
|
|
||||||
|
|
||||||
|
auto rpc_path = String::format("/tmp/rpc.%d", getpid());
|
||||||
|
rc = unlink(rpc_path.characters());
|
||||||
|
if (rc < 0 && errno != ENOENT) {
|
||||||
|
perror("unlink");
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
bool listening = s_rpc_server.listen(rpc_path);
|
||||||
|
ASSERT(listening);
|
||||||
|
|
||||||
|
s_rpc_server.on_ready_to_accept = [&] {
|
||||||
|
auto* client = s_rpc_server.accept();
|
||||||
|
ASSERT(client);
|
||||||
|
JsonArray objects;
|
||||||
|
for (auto& object : CObject::all_objects()) {
|
||||||
|
JsonObject json_object;
|
||||||
|
json_object.set("class_name", object.class_name());
|
||||||
|
json_object.set("address", String::format("%p", &object));
|
||||||
|
json_object.set("name", object.name());
|
||||||
|
json_object.set("parent", String::format("%p", object.parent()));
|
||||||
|
objects.append(move(json_object));
|
||||||
|
}
|
||||||
|
client->write(objects.to_string());
|
||||||
|
client->delete_later();
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CEVENTLOOP_DEBUG
|
#ifdef CEVENTLOOP_DEBUG
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
#include <LibCore/CLock.h>
|
|
||||||
#include <LibCore/CEvent.h>
|
#include <LibCore/CEvent.h>
|
||||||
|
#include <LibCore/CLocalServer.h>
|
||||||
|
#include <LibCore/CLock.h>
|
||||||
#include <sys/select.h>
|
#include <sys/select.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -85,4 +86,6 @@ private:
|
||||||
static int s_next_timer_id;
|
static int s_next_timer_id;
|
||||||
|
|
||||||
static HashTable<CNotifier*>* s_notifiers;
|
static HashTable<CNotifier*>* s_notifiers;
|
||||||
|
|
||||||
|
static CLocalServer s_rpc_server;
|
||||||
};
|
};
|
||||||
|
|
42
Userland/rpcdump.cpp
Normal file
42
Userland/rpcdump.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#include <LibCore/CEventLoop.h>
|
||||||
|
#include <LibCore/CLocalSocket.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("usage: %s <pid>\n", argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
CEventLoop loop;
|
||||||
|
|
||||||
|
int pid = atoi(argv[1]);
|
||||||
|
|
||||||
|
CLocalSocket socket;
|
||||||
|
auto success = socket.connect(CSocketAddress::local(String::format("/tmp/rpc.%d", pid)));
|
||||||
|
if (!success) {
|
||||||
|
fprintf(stderr, "Couldn't connect to PID %d\n", pid);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on_connected = [&] {
|
||||||
|
dbg() << "Connected to PID " << pid;
|
||||||
|
};
|
||||||
|
|
||||||
|
socket.on_ready_to_read = [&] {
|
||||||
|
if (socket.eof()) {
|
||||||
|
dbg() << "Disconnected from PID " << pid;
|
||||||
|
loop.quit(0);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto data = socket.read_all();
|
||||||
|
|
||||||
|
for (int i = 0; i < data.size(); ++i)
|
||||||
|
putchar(data[i]);
|
||||||
|
printf("\n");
|
||||||
|
};
|
||||||
|
|
||||||
|
return loop.exec();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue