From 7582ab165b4c57d2325561b59d99a6665af28cc3 Mon Sep 17 00:00:00 2001 From: Adrian Kummerlaender Date: Thu, 11 Feb 2016 18:43:27 +0100 Subject: Delay tracking activation Introduce global static `enabled` variable used to signal the interposed functions to either start tracking or perform plain forwarding without any additional logic. This is required as e.g. `nvim` crashed when wrapped in `libChangeLog` because it called interposed functions during library initialization. --- src/change_log.cc | 65 +++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 21 deletions(-) diff --git a/src/change_log.cc b/src/change_log.cc index a6f1437..8ff99e4 100644 --- a/src/change_log.cc +++ b/src/change_log.cc @@ -8,20 +8,14 @@ #include "utility/logger.h" #include "tracking/change_tracker.h" +// `true` signals the interposed functions to execute tracking logic +// `false` signals the interposed functions to do plain forwarding +static bool enabled = false; + static std::unique_ptr fd_guard; static std::unique_ptr logger; static std::unique_ptr tracker; -void track_write(const int fd) { - if ( fd != *fd_guard && utility::is_regular_file(fd) ) { - const std::string file_name{ utility::get_file_name(fd) }; - - if ( !tracker->is_tracked(file_name) ) { - tracker->track(file_name); - } - } -} - void init() __attribute__ ((constructor)); void init() { if ( getenv("CHANGE_LOG_TARGET") != NULL ) { @@ -40,6 +34,41 @@ void init() { } else { tracker = std::make_unique(logger.get()); } + + // tracking is only enabled when everything is initialized as both + // the actual tracking and the decision if a event should be tracked + // depend on `logger` and `tracker` being fully instantiated. + // In most cases this library will work correctly without delayed + // activation but e.g. `nvim` crashes as it performs tracked syscalls + // before `init` has been called. + enabled = true; +} + +inline void track_write(const int fd) { + if ( enabled && fd != *fd_guard && utility::is_regular_file(fd) ) { + const std::string file_name{ utility::get_file_name(fd) }; + + if ( !tracker->is_tracked(file_name) ) { + tracker->track(file_name); + } + } +} + +inline void track_rename( + const std::string& old_path, const std::string& new_path) { + if ( enabled ) { + if ( !tracker->is_tracked(old_path) ) { + tracker->track(old_path); + } + + logger->append("renamed '", old_path, "' to '", new_path, "'"); + } +} + +inline void track_remove(const std::string& path) { + if ( enabled && utility::is_regular_file(path.c_str()) ) { + logger->append("removed '", path, "'"); + } } ssize_t write(int fd, const void* buffer, size_t count) { @@ -55,34 +84,28 @@ ssize_t writev(int fd, const iovec* iov, int iovcnt) { } int rename(const char* old_path, const char* new_path) { - if ( !tracker->is_tracked(old_path) ) { - tracker->track(old_path); - } - - logger->append("renamed '", old_path, "' to '", new_path, "'"); + track_rename(old_path, new_path); return actual::rename(old_path, new_path); } int rmdir(const char* path) { - logger->append("removed directory '", path, "'"); + track_remove(path); return actual::rmdir(path); } int unlink(const char* path) { - if ( utility::is_regular_file(path) ) { - logger->append("remove '", path, "'"); - } + track_remove(path); return actual::unlink(path); } int unlinkat(int dirfd, const char* path, int flags) { if ( dirfd == AT_FDCWD ) { - logger->append("removed '", path, "'"); + track_remove(path); } else { - logger->append("removed '", utility::get_file_name(dirfd), path, "'"); + track_remove(utility::get_file_name(dirfd) + path); } return actual::unlinkat(dirfd, path, flags); -- cgit v1.2.3