Compare commits

...

15 Commits

Author SHA1 Message Date
rakshasa f9b9629235 Merge branch 'master' into feature/ipc-worker 2026-09-15 14:40:49 +02:00
noctuum 282c86597a Fix a use after free in the xmlrpc-c index path
The string was freed before it was tested, and tmp was never released.
2026-09-14 11:32:11 +02:00
noctuum c41e63248a Check the flush and sync on session file writes
good() was checked before close(), where the data is actually flushed.
2026-09-14 11:10:12 +02:00
noctuum 641626029a Fix a one byte write past address_copy
The index bound was the buffer size, not the last writable index.
2026-09-14 10:53:12 +02:00
rakshasa cc1fcbe3e5 Merge branch 'master' into feature/ipc-worker 2026-08-16 14:29:32 +02:00
rakshasa 877e5f6ed3 Stuff. 2026-08-09 22:49:49 +02:00
rakshasa ee64f8ea50 Merge branch 'master' into feature/ipc-worker 2026-08-09 13:13:20 +02:00
rakshasa bf1265d954 Stuff. 2026-08-09 10:44:29 +02:00
rakshasa 6c3c77a2b7 Stuff. 2026-08-07 11:58:33 +02:00
rakshasa 120fcb0273 Merge branch 'master' into feature/ipc-worker 2026-08-06 11:03:44 +02:00
rakshasa c36956813d Merge branch 'master' into feature/ipc-worker 2026-08-04 18:00:04 +02:00
rakshasa 05563b4c9b Stuff. 2026-07-28 10:56:25 +02:00
rakshasa a544f8ad68 Merge branch 'master' into feature/ipc-worker 2026-07-28 10:33:57 +02:00
rakshasa b35413ea71 Merge branch 'master' into feature/ipc-worker 2026-07-26 13:03:33 +02:00
rakshasa f9f19fb041 Stuff. 2026-07-26 09:14:39 +02:00
10 changed files with 47 additions and 33 deletions
+1 -1
View File
@@ -131,7 +131,7 @@ ipv4_range_parse(const char* address, uint32_t* address_start, uint32_t* address
// copy everything up to '#' to address_copy and work from there
while(address[address_start_index] != '#' && address[address_start_index] != '\r' &&
address[address_start_index] != '\n' && address[address_start_index] != '\0' &&
address_start_index < 4096 ) {
address_start_index < 4095 ) {
address_copy[address_start_index] = address[address_start_index];
address_start_index++;
+1 -2
View File
@@ -11,8 +11,7 @@ namespace input {
void
InputEvent::insert() {
torrent::this_thread::poll()->open(this);
torrent::this_thread::poll()->insert_read(this);
torrent::this_thread::poll()->open_and_insert_read(this);
}
void
+16 -15
View File
@@ -112,8 +112,9 @@ main(int argc, char** argv) {
torrent::log_initialize();
// TODO: Create a fake thread object for initializing other processes and enabling logging.
torrent::initialize_main_thread();
torrent::runtime::initialize_worker_process_and_main_thread([argc, argv]() {
parse_config_file(argc, argv, [](auto& path) { parse_config_file_comments("worker", path); });
});
// Block SIGCHLD until all threads are created, then unblock on main-thread, to avoid SIGCHLD
// interrupting other threads.
@@ -125,9 +126,9 @@ main(int argc, char** argv) {
SignalHandler::set_block(SIGCHLD);
// All signal handlers must restore errno if they return.
SignalHandler::set_handler(SIGSEGV, std::bind(&do_panic, SIGSEGV));
SignalHandler::set_handler(SIGILL, std::bind(&do_panic, SIGILL));
SignalHandler::set_handler(SIGFPE, std::bind(&do_panic, SIGFPE));
SignalHandler::set_handler(SIGSEGV, []() { do_panic(SIGSEGV); });
SignalHandler::set_handler(SIGILL, []() { do_panic(SIGILL); });
SignalHandler::set_handler(SIGFPE, []() { do_panic(SIGFPE); });
// Limited list of commands with the following format:
//
@@ -136,19 +137,17 @@ main(int argc, char** argv) {
// # do:log.open_file=system,/usr/rakshasa/system.log
// # do:log.add_output=system,system
//
parse_config_file(argc, argv, [](auto& path) {
if (path.empty())
return;
parse_config_file_comments(path);
});
// # do-worker:log.open_file=system,/usr/rakshasa/system-worker.log
// # do-worker:log.add_output=system,system
//
parse_config_file(argc, argv, [](auto& path) { parse_config_file_comments("", path); });
control = new Control;
SignalHandler::set_handler(SIGINT, std::bind(&Control::receive_normal_shutdown, control));
SignalHandler::set_handler(SIGHUP, std::bind(&Control::receive_normal_shutdown, control));
SignalHandler::set_handler(SIGTERM, std::bind(&Control::receive_quick_shutdown, control));
SignalHandler::set_handler(SIGWINCH, std::bind(&display::Manager::force_redraw, control->display()));
SignalHandler::set_handler(SIGINT, []() { control->receive_normal_shutdown(); });
SignalHandler::set_handler(SIGHUP, []() { control->receive_normal_shutdown(); });
SignalHandler::set_handler(SIGTERM, []() { control->receive_quick_shutdown(); });
SignalHandler::set_handler(SIGWINCH, []() { control->display()->force_redraw(); });
SignalHandler::set_sigaction_handler(SIGBUS, &handle_sigbus);
@@ -469,6 +468,8 @@ main(int argc, char** argv) {
control->ui()->load_input_history();
torrent::net_thread::http_stack()->set_user_agent(USER_AGENT);
torrent::runtime::initialize_worker_process();
torrent::runtime::initialize_network();
// Load session torrents and perform scheduled tasks to ensure session torrents are loaded
+1 -1
View File
@@ -108,6 +108,6 @@ OptionParser::call_int_pair(slot_int_pair slot, const std::string& arg) {
if (a < 0 || b < 0)
throw std::runtime_error("Invalid argument, \"" + arg + "\" should be positive numbers");
slot(a, b);
}
+1 -2
View File
@@ -109,8 +109,7 @@ void
SCgi::activate() {
assert(torrent::this_thread::thread() == scgi_thread::thread());
torrent::this_thread::poll()->open(this);
torrent::this_thread::poll()->insert_read(this);
torrent::this_thread::poll()->open_and_insert_read(this);
}
// TODO: This should close the fd to avoid reuse.
+1 -2
View File
@@ -50,8 +50,7 @@ SCgiTask::open(SCgi* parent, int fd) {
// m_trusted=false into the next reuse, given that the
// UNTRUSTED_CONNECTION=0 parse branch is a no-op.
torrent::this_thread::poll()->open(this);
torrent::this_thread::poll()->insert_read(this);
torrent::this_thread::poll()->open_and_insert_read(this);
torrent::this_thread::scheduler()->update_wait_for_ceil_seconds(&m_task_timeout, timeout_request);
+3 -1
View File
@@ -77,16 +77,18 @@ xmlrpc_list_entry_to_value(xmlrpc_env* env, xmlrpc_value* src, int index) {
{
const char* str;
xmlrpc_read_string(env, tmp, &str);
xmlrpc_DECREF(tmp);
if (env->fault_occurred)
throw xmlrpc_error_c(env);
const char* end = str;
int64_t v3 = ::strtoll(str, (char**)&end, 0);
bool invalid = *str == '\0' || *end != '\0';
::free((void*)str);
if (*str == '\0' || *end != '\0')
if (invalid)
throw xmlrpc_error_c(XMLRPC_TYPE_ERROR, "Invalid index.");
return v3;
+13 -3
View File
@@ -127,8 +127,12 @@ save_stream(const std::string& path, bool use_fsyncdisk, const std::stringstream
if (!output.good())
throw torrent::storage_error("failed to write stream to file : " + path);
// The data only reaches the kernel here, so this is where a full disk is seen.
output.close();
if (!output.good())
throw torrent::storage_error("failed to flush stream to file : " + path);
// Ensure that the new file is actually written to the disk
int fd = ::open(path.c_str(), O_WRONLY);
@@ -137,13 +141,19 @@ save_stream(const std::string& path, bool use_fsyncdisk, const std::stringstream
if (use_fsyncdisk) {
#ifdef __APPLE__
::fsync(fd);
int sync_result = ::fsync(fd);
#else
::fdatasync(fd);
int sync_result = ::fdatasync(fd);
#endif
if (sync_result == -1) {
::close(fd);
throw torrent::storage_error("failed to sync file to disk : " + path);
}
}
::close(fd);
if (::close(fd) == -1)
throw torrent::storage_error("failed to close file descriptor : " + path);
}
} // namespace anonymous
+9 -5
View File
@@ -108,18 +108,22 @@ config_comment_log(const std::string& command, const std::string& raw_args) {
throw torrent::input_error("Unknown log command: " + command);
}
// Call special commands in the format "# do:command=args" in the config file.
// Call special commands in the format "# do:command=args" or "# do-<category>:command=args" in the config file.
void
parse_config_file_comments(const std::string& path) {
parse_config_file_comments(const std::string& category, const std::string& path) {
if (path.empty())
return;
std::fstream file(path, std::ios::in);
if (!file.is_open())
return;
std::string line;
std::string prefix = category.empty() ? "# do:" : "# do-" + category + ":";
while (std::getline(file, line)) {
if (line.size() <= 5 || line.compare(0, 5, "# do:") != 0)
if (line.size() <= prefix.size() || line.compare(0, prefix.size(), prefix) != 0)
continue;
auto equal_pos = line.find('=');
@@ -127,8 +131,8 @@ parse_config_file_comments(const std::string& path) {
if (equal_pos == std::string::npos)
throw torrent::input_error("Invalid command in config file comment: " + line);
std::string command = line.substr(5, equal_pos - 5);
std::string args = line.substr(equal_pos + 1);
auto command = line.substr(prefix.size(), equal_pos - prefix.size());
auto args = line.substr(equal_pos + 1);
if (command.empty())
throw torrent::input_error("Invalid command in config file comment: " + line);
+1 -1
View File
@@ -7,7 +7,7 @@
int parse_main_options(int argc, char** argv);
void parse_config_file(int argc, char** argv, std::function<void (const std::string&)> parse_fn);
void parse_config_file_comments(const std::string& path);
void parse_config_file_comments(const std::string& category, const std::string& path);
void load_session_torrents(const std::string& path);
void load_arg_torrents(char** first, char** last);