void buffered_log_stream::watch_removed() noexcept
{
if (fd > STDERR_FILENO) {
- close(fd);
+ bp_sys::close(fd);
fd = -1;
}
// Here we rely on there only being two logs, console and "main"; we can check if we are the
log_format_syslog[DLOG_MAIN] = syslog_format;
}
+// Close logging subsystem
+void close_log()
+{
+ if (log_stream[DLOG_CONS].fd != -1) log_stream[DLOG_CONS].deregister(event_loop);
+ if (log_stream[DLOG_MAIN].fd != -1) log_stream[DLOG_MAIN].deregister(event_loop);
+}
+
// Set up the main log to output to the given file descriptor.
// Potentially throws std::bad_alloc or std::system_error
void setup_main_log(int fd)
void enable_console_log(bool do_enable) noexcept;
void init_log(service_set *sset, bool syslog_format);
+void close_log();
void setup_main_log(int fd);
bool is_log_flushed() noexcept;
void discard_console_log_buffer() noexcept;
-#include <cassert>
#include <iostream>
+#include <cerrno>
+#include <cassert>
+
#include "service.h"
#include "test_service.h"
#include "baseproc-sys.h"
void test_log1()
{
+ // Basic test that output to log is written to log file
service_set sset;
init_log(&sset, true /* syslog format */);
std::string wstr {wdata.begin(), wdata.end()};
assert(wstr == "<27>dinit: test one\n");
+ close_log();
+}
+
+void test_log2()
+{
+ // test that log is closed on write failure.
+ service_set sset;
+ init_log(&sset, true /* syslog format */);
+
+ bool was_closed = false;
+
+ class fail_writer : public bp_sys::write_handler {
+ public:
+ bool *was_closed = nullptr;
+
+ ssize_t write(int fd, const void *buf, size_t count) override
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+
+ ~fail_writer() override
+ {
+ *was_closed = true;
+ }
+ };
+
+ fail_writer *fw = new fail_writer();
+ fw->was_closed = &was_closed;
+
+ int logfd = bp_sys::allocfd(fw);
+ setup_main_log(logfd);
+
+ event_loop.send_fd_event(logfd, dasynq::OUT_EVENTS);
+ event_loop.send_fd_event(STDOUT_FILENO, dasynq::OUT_EVENTS);
+
+ log(loglevel_t::ERROR, "test two");
+
+ // flush
+ //event_loop.
+ event_loop.send_fd_event(logfd, dasynq::OUT_EVENTS);
+
+ assert(was_closed);
+ close_log();
}
#define RUN_TEST(name, spacing) \
int main(int argc, char **argv)
{
+ bp_sys::init_bpsys();
+
RUN_TEST(test1, " ");
RUN_TEST(test2, " ");
RUN_TEST(test3, " ");
RUN_TEST(test14, " ");
RUN_TEST(test15, " ");
RUN_TEST(test_log1, " ");
+ RUN_TEST(test_log2, " ");
}