From a38a0bb0f2cffb723002477ee1036539abfa6ad6 Mon Sep 17 00:00:00 2001 From: David Boucher Date: Wed, 13 Oct 2021 18:37:27 +0200 Subject: [PATCH] fix(clib): clib headers synchronized --- neb/inc/com/centreon/exceptions/basic.hh | 2 +- .../com/centreon/exceptions/interruption.hh | 2 +- neb/inc/com/centreon/io/directory_entry.hh | 4 +- neb/inc/com/centreon/io/file_entry.hh | 6 +- neb/inc/com/centreon/io/file_stream.hh | 2 +- neb/inc/com/centreon/logging/backend.hh | 9 +- neb/inc/com/centreon/logging/engine.hh | 2 +- neb/inc/com/centreon/logging/file.hh | 2 +- neb/inc/com/centreon/logging/logger.hh | 20 ++--- neb/inc/com/centreon/logging/syslogger.hh | 2 +- neb/inc/com/centreon/logging/temp_logger.hh | 4 +- neb/inc/com/centreon/misc/argument.hh | 2 +- neb/inc/com/centreon/misc/command_line.hh | 2 +- neb/inc/com/centreon/misc/get_options.hh | 4 +- neb/inc/com/centreon/misc/stringifier.hh | 2 +- neb/inc/com/centreon/process.hh | 47 +++++++--- neb/inc/com/centreon/process_manager.hh | 90 +++++++++++++------ 17 files changed, 128 insertions(+), 74 deletions(-) diff --git a/neb/inc/com/centreon/exceptions/basic.hh b/neb/inc/com/centreon/exceptions/basic.hh index 442f2ea3e..4ff4c7f82 100644 --- a/neb/inc/com/centreon/exceptions/basic.hh +++ b/neb/inc/com/centreon/exceptions/basic.hh @@ -50,7 +50,7 @@ class basic : public std::exception { misc::stringifier _buffer; }; -} +} // namespace exceptions CC_END() diff --git a/neb/inc/com/centreon/exceptions/interruption.hh b/neb/inc/com/centreon/exceptions/interruption.hh index 5c5d47f73..e3f25e3be 100644 --- a/neb/inc/com/centreon/exceptions/interruption.hh +++ b/neb/inc/com/centreon/exceptions/interruption.hh @@ -47,7 +47,7 @@ class interruption : public basic { return (*this); } }; -} +} // namespace exceptions CC_END() diff --git a/neb/inc/com/centreon/io/directory_entry.hh b/neb/inc/com/centreon/io/directory_entry.hh index cf6ebf3ab..a6a755bb9 100644 --- a/neb/inc/com/centreon/io/directory_entry.hh +++ b/neb/inc/com/centreon/io/directory_entry.hh @@ -21,8 +21,8 @@ #include #include -#include "com/centreon/io/file_entry.hh" #include "com/centreon/handle.hh" +#include "com/centreon/io/file_entry.hh" #include "com/centreon/namespace.hh" CC_BEGIN() @@ -55,7 +55,7 @@ class directory_entry { file_entry _entry; std::list _entry_lst; }; -} +} // namespace io CC_END() diff --git a/neb/inc/com/centreon/io/file_entry.hh b/neb/inc/com/centreon/io/file_entry.hh index cd3576d0e..ce9b240da 100644 --- a/neb/inc/com/centreon/io/file_entry.hh +++ b/neb/inc/com/centreon/io/file_entry.hh @@ -19,9 +19,9 @@ #ifndef CC_IO_FILE_ENTRY_HH #define CC_IO_FILE_ENTRY_HH -#include -#include #include +#include +#include #include "com/centreon/handle.hh" #include "com/centreon/namespace.hh" @@ -65,7 +65,7 @@ class file_entry { std::string _path; struct stat _sbuf; }; -} +} // namespace io CC_END() diff --git a/neb/inc/com/centreon/io/file_stream.hh b/neb/inc/com/centreon/io/file_stream.hh index 8737b6258..9f31b6ed7 100644 --- a/neb/inc/com/centreon/io/file_stream.hh +++ b/neb/inc/com/centreon/io/file_stream.hh @@ -63,7 +63,7 @@ class file_stream : public handle { bool _auto_close; FILE* _stream; }; -} +} // namespace io CC_END() diff --git a/neb/inc/com/centreon/logging/backend.hh b/neb/inc/com/centreon/logging/backend.hh index 6da9ee6fb..2864f6661 100644 --- a/neb/inc/com/centreon/logging/backend.hh +++ b/neb/inc/com/centreon/logging/backend.hh @@ -29,12 +29,7 @@ class stringifier; } namespace logging { -enum time_precision { - none = 0, - microsecond = 1, - millisecond = 2, - second = 3 -}; +enum time_precision { none = 0, microsecond = 1, millisecond = 2, second = 3 }; /** * @class backend backend.hh "com/centreon/logging/backend.hh" @@ -81,7 +76,7 @@ class backend { protected: void _internal_copy(backend const& right); }; -} +} // namespace logging CC_END() diff --git a/neb/inc/com/centreon/logging/engine.hh b/neb/inc/com/centreon/logging/engine.hh index 016450c4e..59bb9a38b 100644 --- a/neb/inc/com/centreon/logging/engine.hh +++ b/neb/inc/com/centreon/logging/engine.hh @@ -89,7 +89,7 @@ class engine { unsigned long long _list_types[sizeof(unsigned int) * CHAR_BIT]; mutable std::mutex _mtx; }; -} +} // namespace logging CC_END() diff --git a/neb/inc/com/centreon/logging/file.hh b/neb/inc/com/centreon/logging/file.hh index c04b2aecc..ed6f33b79 100644 --- a/neb/inc/com/centreon/logging/file.hh +++ b/neb/inc/com/centreon/logging/file.hh @@ -68,7 +68,7 @@ class file : public backend { FILE* _out; uint64_t _size; }; -} +} // namespace logging CC_END() diff --git a/neb/inc/com/centreon/logging/logger.hh b/neb/inc/com/centreon/logging/logger.hh index 42b809b93..69aced161 100644 --- a/neb/inc/com/centreon/logging/logger.hh +++ b/neb/inc/com/centreon/logging/logger.hh @@ -30,20 +30,16 @@ enum type_value { type_error = (1ull << 63) }; -enum verbosity_level { - low = 0, - medium = 1, - high = 2 -}; -} +enum verbosity_level { low = 0, medium = 1, high = 2 }; +} // namespace logging CC_END() #define log_info(verbose) \ for (unsigned int __com_centreon_logging_define_ui(0); \ !__com_centreon_logging_define_ui && \ - com::centreon::logging::engine::instance().is_log( \ - com::centreon::logging::type_info, verbose); \ + com::centreon::logging::engine::instance().is_log( \ + com::centreon::logging::type_info, verbose); \ ++__com_centreon_logging_define_ui) \ com::centreon::logging::temp_logger(com::centreon::logging::type_info, \ verbose) \ @@ -52,8 +48,8 @@ CC_END() #define log_debug(verbose) \ for (unsigned int __com_centreon_logging_define_ui(0); \ !__com_centreon_logging_define_ui && \ - com::centreon::logging::engine::instance().is_log( \ - com::centreon::logging::type_debug, verbose); \ + com::centreon::logging::engine::instance().is_log( \ + com::centreon::logging::type_debug, verbose); \ ++__com_centreon_logging_define_ui) \ com::centreon::logging::temp_logger(com::centreon::logging::type_debug, \ verbose) \ @@ -62,8 +58,8 @@ CC_END() #define log_error(verbose) \ for (unsigned int __com_centreon_logging_define_ui(0); \ !__com_centreon_logging_define_ui && \ - com::centreon::logging::engine::instance().is_log( \ - com::centreon::logging::type_error, verbose); \ + com::centreon::logging::engine::instance().is_log( \ + com::centreon::logging::type_error, verbose); \ ++__com_centreon_logging_define_ui) \ com::centreon::logging::temp_logger(com::centreon::logging::type_error, \ verbose) \ diff --git a/neb/inc/com/centreon/logging/syslogger.hh b/neb/inc/com/centreon/logging/syslogger.hh index c0ec7e6a1..b69935628 100644 --- a/neb/inc/com/centreon/logging/syslogger.hh +++ b/neb/inc/com/centreon/logging/syslogger.hh @@ -54,7 +54,7 @@ class syslogger : public backend { int _facility; std::string _id; }; -} +} // namespace logging CC_END() diff --git a/neb/inc/com/centreon/logging/temp_logger.hh b/neb/inc/com/centreon/logging/temp_logger.hh index d2d0cfc95..1527dd4a3 100644 --- a/neb/inc/com/centreon/logging/temp_logger.hh +++ b/neb/inc/com/centreon/logging/temp_logger.hh @@ -21,8 +21,8 @@ #include #include "com/centreon/logging/engine.hh" -#include "com/centreon/namespace.hh" #include "com/centreon/misc/stringifier.hh" +#include "com/centreon/namespace.hh" CC_BEGIN() @@ -59,7 +59,7 @@ class temp_logger { unsigned long long _type; unsigned int _verbose; }; -} +} // namespace logging CC_END() diff --git a/neb/inc/com/centreon/misc/argument.hh b/neb/inc/com/centreon/misc/argument.hh index d0c32dcb4..6566b725a 100644 --- a/neb/inc/com/centreon/misc/argument.hh +++ b/neb/inc/com/centreon/misc/argument.hh @@ -67,7 +67,7 @@ class argument { char _name; std::string _value; }; -} +} // namespace misc CC_END() diff --git a/neb/inc/com/centreon/misc/command_line.hh b/neb/inc/com/centreon/misc/command_line.hh index 7182df6e6..ce44383d4 100644 --- a/neb/inc/com/centreon/misc/command_line.hh +++ b/neb/inc/com/centreon/misc/command_line.hh @@ -55,7 +55,7 @@ class command_line { char** _argv; size_t _size; }; -} +} // namespace misc CC_END() diff --git a/neb/inc/com/centreon/misc/get_options.hh b/neb/inc/com/centreon/misc/get_options.hh index 1d81b06c2..8eca923d7 100644 --- a/neb/inc/com/centreon/misc/get_options.hh +++ b/neb/inc/com/centreon/misc/get_options.hh @@ -22,8 +22,8 @@ #include #include #include -#include "com/centreon/namespace.hh" #include "com/centreon/misc/argument.hh" +#include "com/centreon/namespace.hh" CC_BEGIN() @@ -74,7 +74,7 @@ class get_options { std::string& key, std::string& value); }; -} +} // namespace misc CC_END() diff --git a/neb/inc/com/centreon/misc/stringifier.hh b/neb/inc/com/centreon/misc/stringifier.hh index c11239f1e..3f640fba2 100644 --- a/neb/inc/com/centreon/misc/stringifier.hh +++ b/neb/inc/com/centreon/misc/stringifier.hh @@ -75,7 +75,7 @@ class stringifier { static unsigned int const _static_buffer_size = 1024; char _static_buffer[_static_buffer_size]; }; -} +} // namespace misc CC_END() diff --git a/neb/inc/com/centreon/process.hh b/neb/inc/com/centreon/process.hh index 02e8d971d..0a4d9e5ec 100644 --- a/neb/inc/com/centreon/process.hh +++ b/neb/inc/com/centreon/process.hh @@ -20,7 +20,10 @@ #define CC_PROCESS_POSIX_HH #include +#include +#include #include +#include #include #include #include "com/centreon/timestamp.hh" @@ -39,27 +42,50 @@ class process_manager; class process { friend class process_manager; + /* Constants */ + const std::array _enable_stream; + process_listener* const _listener; + + /* Constants except during exec() call */ + uint32_t _timeout; + + /* Constants except when they are initialized at exec() and closed when + * process is over. */ + std::atomic_bool _is_timeout; + std::atomic_int _status; + std::array _stream; + pid_t _process; + + /* Almost never changed, we have two such functions, one with pgid and the + * other without. */ + pid_t (*_create_process)(char**, char**); + public: enum status { normal = 0, crash = 1, timeout = 2 }; enum stream { in = 0, out = 1, err = 2 }; private: + /* Error buffer: + * * cleared by exec(), + * * content get and then cleared by read_err() + * * and filled by do_read() when an error in the process occures. This last + * method is called by the process manager in its main loop when needed. + */ std::string _buffer_err; + + /* Output buffer: + * * cleared by exec(), + * * content get and then cleared by read() + * * and filled by do_read() when an output in the process occures. This last + * method is called by the process manager in its main loop when needed. + */ std::string _buffer_out; - pid_t (*_create_process)(char**, char**); mutable std::condition_variable _cv_buffer_err; mutable std::condition_variable _cv_buffer_out; mutable std::condition_variable _cv_process_running; - const std::array _enable_stream; - std::array _stream; timestamp _end_time; - bool _is_timeout; - process_listener* _listener; mutable std::mutex _lock_process; - pid_t _process; timestamp _start_time; - int _status; - uint32_t _timeout; static void _close(int& fd) noexcept; static pid_t _create_process_with_setpgid(char** args, char** env); @@ -88,7 +114,7 @@ class process { void exec(std::string const& cmd, uint32_t timeout = 0); int exit_code() const noexcept; status exit_status() const noexcept; - void kill(); + void kill(int sig = SIGKILL); void read(std::string& data); void read_err(std::string& data); void setpgid_on_exec(bool enable) noexcept; @@ -97,9 +123,10 @@ class process { void terminate(); void wait() const; bool wait(uint32_t timeout) const; - void update_ending_process(int status); uint32_t write(std::string const& data); uint32_t write(void const* data, uint32_t size); + void update_ending_process(int status); + void set_timeout(bool timeout); }; CC_END() diff --git a/neb/inc/com/centreon/process_manager.hh b/neb/inc/com/centreon/process_manager.hh index a8af51da2..3ba92da67 100644 --- a/neb/inc/com/centreon/process_manager.hh +++ b/neb/inc/com/centreon/process_manager.hh @@ -1,5 +1,5 @@ /* -** Copyright 2012-2013,2019 Centreon +** Copyright 2012-2013,2019-2021 Centreon ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. @@ -40,24 +40,59 @@ class process_listener; *"com/centreon/process_manager_posix.hh" * @brief This class manage process. * - * This class is a singleton, it manages processes. When it is instantiated, it - *starts a thread running the main loop inside the _run() method. This _run - *method is executed with a condition variable _running_cv and a boolean - *running. The constructor is released only when the boolean is set to true, - *that is to say, the loop is really started. + * This class is a singleton, it manages processes by doing two things: + * * waitpid() so it knows when a process is over. + * * poll() so it knows when operations are available on fds. + * + * This singleton starts a thread running the main loop inside the _run() + * method. This method is executed with a condition variable _running_cv and a + * boolean _running. The constructor is released only when the boolean is set + * to true, that is to say, the loop is really started. * * Once the loop is correctly started, the user can add to it processes. This - *is done with the add() method. Since the main loop is running while we add a - *process, a mutex _lock_processes is used. During the add action, - * * A map _processes_fd is completed, this one returns a process knowing its - *output fd or its error fd. - * * If the process is configured with a timeout, the table _processes_timeout - *is also filled ; with it, from a timeout, we can get its process. It is a - *multimap. - * * It is also asked the file descriptors list to be updated by setting the - *_update boolean to true. - * * The process is stored in the _processes_pid table, here it is stored by - *pid. + * is done with the add() method. An important point is poll() and waitpid() + * are called one after the other. And it is really better if no processes + * are added between the two calls. So to avoid this case, processes are + * inserted in the manager during the _update_list() internal function. + * + * A good point that comes with this fact, is that we don't need mutex to + * access data in the manager. + * + * The add() method locks a mutex _add_m and fills a queue _processes then + * set the _update flag to true. Since a process can be closed very quickly + * the _processes queue contains a pair with the pid and the process, because + * when a process finishes, its _process attribute (the pid) is set to -1, so + * we could loose its original value. + * + * When _update_list() is called, _add_m is locked, the queue is exchanged with + * an internal one and _update is set to false. Then _update_list() can work + * on its queue without being disturbed by new coming processes. + * + * The main goal of _update_list() is to update various tables and arrays, the + * main ones are: + * * _fds which is an array of struct pollfd needed by the poll() function. + * * _processes_fd which is a table keeping relations between fds and + * processes. + * * _processes_pid which is a table giving relations between pids and + * processes. + * * _processes_timeout which gives the time limit of a process, after this + * time, the process is killed. + * * We also have _orphans_pid that is almost empty. But it is not always the + * case. Processes can be launched before they are referenced into _fds and + * the several tables. In that case, particularly when they finish quickly + * they may be catch by the waitpid function. And since we don't have them + * in _processes_pid and others, we store them in _orphans_pid. Then later, + * they should appear in others tables and the manager will be able to clear + * them correctly. + * + * The class attributes: + * * _running is a boolean telling if the main loop is running. + * * _running_m/_running_cv are mutex/condition_variable controlling the start + * of the main loop and also used to tell a process, it is no more referenced + * in the manager (see _wait_for_update() method). + * * _finished is a boolean telling when the destructor has been called. All + * the stuff needed to stop the loop are done in it, this is because the + * destructor may be called from another thread and we want to avoid mutexes. */ class process_manager { struct orphan { @@ -69,26 +104,25 @@ class process_manager { * A boolean set to true when file descriptors list needs to be updated. */ std::atomic_bool _update; + std::vector _fds; - /** - * Here is a boolean telling if the main loop is running or not. This variable - * is set to true when the main loop starts and is set to false by the - * process_manager destructor when we want to stop it. - */ + std::unordered_map _processes_fd; std::atomic_bool _running; - std::mutex _running_m; - std::condition_variable _running_cv; + std::atomic_bool _finished; + mutable std::mutex _running_m; + mutable std::condition_variable _running_cv; std::thread _thread; - mutable std::mutex _lock_processes; - std::unordered_map _processes_fd; std::deque _orphans_pid; std::unordered_map _processes_pid; + mutable std::mutex _timeout_m; std::multimap _processes_timeout; + mutable std::mutex _add_m; + std::deque> _processes; + process_manager(); ~process_manager() noexcept; - static void _close(int& fd) noexcept; void _close_stream(int fd) noexcept; void _erase_timeout(process* p); void _kill_processes_timeout() noexcept; @@ -98,12 +132,14 @@ class process_manager { void _update_list(); void _wait_orphans_pid() noexcept; void _wait_processes() noexcept; + void _stop_processes() noexcept; public: void add(process* p); static process_manager& instance(); process_manager& operator=(process_manager const& p) = delete; process_manager(process_manager const& p) = delete; + void wait_for_update() const noexcept; }; CC_END()