Skip to content

Commit

Permalink
TgBot++: android_builder: Further fixup
Browse files Browse the repository at this point in the history
- ForkAndRun provides a shmem interface for interaction with forked process
- ROMBuildTask splitted to cpp
  • Loading branch information
Royna2544 committed Jul 6, 2024
1 parent 824b4f4 commit 14640f8
Show file tree
Hide file tree
Showing 10 changed files with 409 additions and 225 deletions.
67 changes: 65 additions & 2 deletions src/android_builder/ForkAndRun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
#include <Python.h>
#include <absl/log/log.h>
#include <absl/log/log_sink_registry.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <internal/_FileDescriptor_posix.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/wait.h>

#include <csignal>
#include <cstdlib>
#include <libos/OnTerminateRegistrar.hpp>
#include <string>
#include <optional>
#include <thread>

#include "random/RandomNumberGenerator.h"
Expand Down Expand Up @@ -140,6 +142,7 @@ bool ForkAndRun::execute() {
selector.remove(stdout_pipe.readEnd());
selector.remove(stderr_pipe.readEnd());
selector.remove(program_termination_pipe.readEnd());
selector.remove(python_pipe.readEnd());
program_termination_pipe.close();
stderr_pipe.close();
stdout_pipe.close();
Expand All @@ -165,4 +168,64 @@ void ForkAndRun::cancel() {
LOG(WARNING) << "Unexpected status: " << status;
}
childProcessId = -1;
}

std::optional<ForkAndRun::Shmem> ForkAndRun::allocShmem(
const std::string_view& path, off_t size) {
void* ptr = nullptr;
int fd = shm_open(path.data(), O_CREAT | O_RDWR, 0666);
if (fd == -1) {
PLOG(ERROR) << "shm_open failed";
return std::nullopt;
}
const auto fdCloser = createFdAutoCloser(&fd);
if (ftruncate(fd, size) == -1) {
PLOG(ERROR) << "ftruncate failed";
return std::nullopt;
}
ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
PLOG(ERROR) << "mmap failed";
return std::nullopt;
}
close(fd);
DLOG(INFO) << "Shmem created with path: " << path.data()
<< " size: " << size << " bytes";
return Shmem{path.data(), size, ptr, true};
}

void ForkAndRun::freeShmem(Shmem& shmem) {
if (munmap(shmem.memory, shmem.size) == -1) {
PLOG(ERROR) << "munmap failed";
}
if (shm_unlink(shmem.path.c_str()) == -1) {
PLOG(ERROR) << "shm_unlink failed";
}
DLOG(INFO) << "Shmem freed";
shmem.isAllocated = false;
}

std::optional<ForkAndRun::Shmem> ForkAndRun::connectShmem(
const std::string_view& path, const off_t size) {
int fd = shm_open(path.data(), O_RDWR, 0);
if (fd == -1) {
PLOG(ERROR) << "shm_open failed";
return std::nullopt;
}
const auto fdCloser = createFdAutoCloser(&fd);
void* ptr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (ptr == MAP_FAILED) {
PLOG(ERROR) << "mmap failed";
return std::nullopt;
}
DLOG(INFO) << "Shmem connected with path: " << path.data();
return Shmem{path.data(), size, ptr, true};
}

void ForkAndRun::disconnectShmem(Shmem& shmem) {
if (munmap(shmem.memory, shmem.size) == -1) {
PLOG(ERROR) << "munmap failed";
}
DLOG(INFO) << "Shmem disconnected";
shmem.isAllocated = false;
}
59 changes: 55 additions & 4 deletions src/android_builder/ForkAndRun.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

// Helper class to fork and run a subprocess with stdout/err
#include <sys/types.h>
#include <unistd.h>

#include <array>
Expand All @@ -16,7 +17,8 @@ struct FDLogSink : public absl::LogSink {
void Send(const absl::LogEntry& logSink) override {
const auto message = logSink.text_message_with_prefix_and_newline();
constexpr std::string_view prefix = "SubProcess: ";
if (isWritable && logSink.log_severity() <= absl::LogSeverity::kWarning) {
if (isWritable &&
logSink.log_severity() <= absl::LogSeverity::kWarning) {
write(stdout_fd, prefix.data(), prefix.size());
write(stdout_fd, message.data(), message.size());
}
Expand Down Expand Up @@ -84,9 +86,7 @@ class ForkAndRun {
*
* @param signal The signal that caused the subprocess to exit.
*/
virtual void onSignal(int signal) {
onExit(signal);
}
virtual void onSignal(int signal) { onExit(signal); }

/**
* @brief The function to be run in the subprocess.
Expand Down Expand Up @@ -117,6 +117,57 @@ class ForkAndRun {
*/
void cancel();

struct Shmem {
std::string path;
off_t size;
void* memory;
bool isAllocated;
};

/**
* @brief Allocates shared memory for the subprocess.
*
* This method allocates shared memory for the subprocess using the
* specified path and size. It returns a pointer to the allocated memory.
*
* @param path The path to the shared memory segment.
* @param size The size of the shared memory segment in bytes.
*
* @return A Shmem object containing the allocated shared memory segment,
* or std::nullopt if the allocation failed.
*/
static std::optional<Shmem> allocShmem(const std::string_view& path,
off_t size);

/**
* @brief Frees the shared memory allocated for the subprocess.
*
* This method frees the shared memory that was allocated for the subprocess
* using the `allocShmem` method. It takes a pointer to the allocated memory
* as an argument and frees the memory associated with it.
*
* @param shmem The Shmem object containing the allocated shared memory
* segment.
*/
static void freeShmem(Shmem& shmem);

/**
* @brief Connects to a shared memory segment.
*
* This method connects to a shared memory segment specified by the given
* path. It returns a pointer to the allocated shared memory segment.
*
* @param path The path to the shared memory segment.
* @param size The size of the shared memory segment.
*
* @return A Shmem object containing the connected shared memory segment,
* or std::nullopt if the connection failed.
*/
static std::optional<Shmem> connectShmem(const std::string_view& path,
const off_t size);

static void disconnectShmem(Shmem& shmem);

private:
UnixSelector selector;
pid_t childProcessId = -1;
Expand Down
15 changes: 15 additions & 0 deletions src/android_builder/scripts/custom_print.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
import os

def custom_print(*args, **kwargs):
"""
This function prints the provided arguments to a file descriptor specified by the environment variable 'PYTHON_LOG_FD'.
Parameters:
*args: Variable length argument list. The values to be printed.
**kwargs: Arbitrary keyword arguments.
sep: String inserted between values, default is a single space.
end: String appended after the last value, default is a newline.
Returns:
None
Raises:
OSError: If the file descriptor is invalid or not open for writing.
"""
logfd = int(os.environ['PYTHON_LOG_FD'])

# Get kwargs or set default values
Expand Down
12 changes: 10 additions & 2 deletions src/android_builder/tasks/PerBuildData.hpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
#pragma once

#include <ConfigParsers.hpp>
#include <absl/log/check.h>

struct PerBuildData {
enum class Result { SUCCESS, ERROR_NONFATAL, ERROR_FATAL };
BuildConfig bConfig;
RomConfig rConfig;
std::filesystem::path scriptDirectory;
struct ResultData {
Result value;
std::string msg;
Result value{};
std::array<char, 250> msg{};
void setMessage(const std::string& message) {
CHECK(message.size() < msg.size());
std::strncpy(msg.data(), message.c_str(), msg.size() - 1);
}
[[nodiscard]] std::string getMessage() const noexcept {
return msg.data();
}
} *result;
};
Loading

0 comments on commit 14640f8

Please sign in to comment.