39#include <snapdev/glob_to_list.h>
52#include <sys/syscall.h>
53#include <sys/sysinfo.h>
59#include <snapdev/poison.h>
125 throw invalid_error(
"runner missing in thread() constructor.");
132 +
") is already in use.");
139 log << log_level_t::fatal
140 <<
"the thread attributes could not be initialized, error #"
144 throw invalid_error(
"pthread_attr_init() failed.");
147 err = pthread_attr_setdetachstate(&
f_thread_attr, PTHREAD_CREATE_JOINABLE);
151 log << log_level_t::fatal
152 <<
"the thread detach state could not be initialized to joinable, error #"
157 throw invalid_error(
"pthread_attr_setdetachstate() failed");
192 log << log_level_t::error
193 <<
"the thread attributes could not be destroyed, error #"
334 if(name.length() > 15)
344 pthread_setname_np(pthread_self(), name.c_str());
368 internal_leave(leave_status_t::LEAVE_STATUS_INITIALIZATION_FAILED);
377 catch(std::exception
const & e)
385 log << log_level_t::fatal
386 <<
"thread internal_thread() got exception: \""
388 <<
"\", exiting thread now."
398 log << log_level_t::fatal
399 <<
"thread internal_thread() got an unknown exception (a.k.a. non-std::exception), exiting process."
441 catch(std::exception
const & e)
449 log << log_level_t::fatal
450 <<
"thread internal_enter() got exception: \""
452 <<
"\", exiting thread now."
490 catch(std::exception
const & e)
498 log << log_level_t::fatal
499 <<
"thread internal_run() got exception: \""
501 <<
"\", exiting thread now."
534 catch(std::exception
const & e)
539 bool force_log(
true);
548 log << log_level_t::fatal
549 <<
"thread internal_leave() got exception: \""
551 <<
"\", exiting thread now."
581 log << log_level_t::warning
582 <<
"the thread is already running."
589 log << log_level_t::warning
590 <<
"the thread runner is not ready."
606 libexcept::scoped_signal_mask::pointer_t block_all_signals;
609 block_all_signals = std::make_shared<libexcept::scoped_signal_mask>();
618 log << log_level_t::error
619 <<
"the thread could not be created, error #"
675 if(callback !=
nullptr)
705 std::exception_ptr e;
707 std::rethrow_exception(e);
896 for(
auto const & s : list)
900 pthread_sigmask(SIG_BLOCK, &set,
nullptr);
931 pthread_sigmask(SIG_BLOCK, &set,
nullptr);
951 for(
auto const & s : list)
955 pthread_sigmask(SIG_UNBLOCK, &set,
nullptr);
981 return get_nprocs_conf();
1033 return get_nprocs();
1049 return static_cast<pid_t
>(syscall(SYS_gettid));
1134 static pid_t pid_max = 0;
1139 in.open(
"/proc/sys/kernel/pid_max", std::ios::in | std::ios::binary);
1143 in.getline(buf,
sizeof(buf) - 1);
1144 buf[
sizeof(buf) - 1] =
'\0';
1145 pid_max = std::stol(buf);
1198 throw invalid_error(
"thread name cannot be empty.");
1200 if(name.length() > 15)
1203 "thread name is limited to 15 characters, \""
1205 +
"\" is too long.");
1219 std::ofstream comm(
"/proc/" + std::to_string(tid) +
"/comm");
1222 return comm ? 0 : -1;
1261 std::ifstream comm(
"/proc/" + std::to_string(tid) +
"/comm");
1287 std::string pattern(
"/proc/");
1288 pattern += std::to_string(pid);
1289 pattern +=
"/task/*";
1291 snapdev::glob_to_list<std::vector<std::string>> glob;
1293 snapdev::glob_to_list_flag_t::GLOB_FLAG_IGNORE_ERRORS
1294 , snapdev::glob_to_list_flag_t::GLOB_FLAG_ONLY_DIRECTORIES>(pattern))
1299 std::string::size_type pos(s.rfind(
'/') + 1);
1301 bool valid(pos < s.length());
1302 for(; pos < s.length(); ++pos)
1304 char const c(s[pos]);
1305 if(c >=
'0' && c <=
'9')
1307 id =
id * 10 + c -
'0';
1317 results.push_back(
id);
1353 std::string proc_path(
"/proc/");
1354 proc_path += std::to_string(pid);
1357 return stat(proc_path.c_str(), &st) == 0;
1374 std::ifstream in(
"/proc/sys/kernel/random/boot_id");
1378 std::getline(in, uuid);
1402 if(stat(
"/proc/self/task", &task) != 0)
1407 return task.st_nlink - 2;
1437 static auto g_vdso(getauxval(AT_SYSINFO_EHDR));
Lock a mutex in an RAII manner.
A mutex object to ensures atomicity.
void wait()
Wait on a mutex condition.
void signal()
Signal at least one mutex.
The runner is the class that wraps the actual system thread.
virtual void enter()
Signal that the run() function is about to be entered.
virtual void run()=0
This virtual function represents the code run by the thread.
std::string const & get_name() const
Retrieve the name of the runner.
virtual void leave(leave_status_t status)
Signal that the run() function has returned.
thread * f_thread
A pointer back to the owner ("parent") of this runner.
virtual bool is_ready() const
Check whether this thread runner is ready.
A thread object that ensures proper usage of system threads.
void mask_all_signals()
Block all signals for this thread.
bool f_stopping
The thread is currently in the stopping process.
void mask_signals(libexcept::sig_list_t list)
Masks signals from this thread.
pid_t f_tid
This thread identifier.
std::exception_ptr f_exception
An exception pointer.
pthread_attr_t f_thread_attr
This thread attributes.
void set_log_all_exceptions(bool log_all_exceptions)
Whether to log exceptions caught in the thread.
void init()
This private function initializes the thread.
runner * get_runner() const
Get a pointer to this thread runner.
std::string const f_name
The name of this thread.
bool is_running() const
Check whether the thread is considered to be running.
bool internal_run()
Execute the run() function.
bool get_log_all_exceptions() const
Retrieve whether all exceptions get logged or not.
friend void * func_internal_start(void *system_thread)
Start the actual thread.
void internal_thread()
Run the thread process.
mutex f_mutex
The thread mutex to guard various functions.
runner * f_runner
The actual thread object.
void stop(std::function< void(thread *)> callback=nullptr)
Stop the thread.
bool is_stopping() const
Check whether the thread was asked to stop.
std::exception_ptr get_exception() const
Get the exception pointer.
pthread_t f_thread_id
This thread identifier.
~thread()
Delete a thread object.
void unmask_signals(libexcept::sig_list_t list)
Unmask signals for this thread.
bool f_started
The thread is started.
std::string const & get_name() const
Retrieve the name of this process object.
bool f_running
The thread is running.
mutex & get_thread_mutex() const
Retrieve a reference to the thread mutex.
thread(std::string const &name, runner *runner)
Initialize the thread object.
bool internal_enter()
Enter the thread runner.
void internal_leave(leave_status_t status)
Function called when leaving the thread runner.
bool start()
Attempt to start the thread.
pid_t get_thread_tid() const
Retrieve the thread identifier of this thread.
bool f_log_all_exceptions
Whether the runner exceptions should be logged or not.
bool kill(int sig)
Send a signal to this thread.
Exceptions for the thread environment.
Thread Runner and Managers.
logger log
The logger object used to send logs out.
Declaration of the log class used to send error messages.
logger & end(logger &l)
Close a log statement.
Thread Runner and Managers.
leave_status_t
The exit status.
bool is_process_running(pid_t pid)
Check whether a process is running or not.
void * func_internal_start(void *system_thread)
Start the actual thread.
pid_t gettid()
Get the thread identifier of the current thread.
std::size_t get_thread_count()
Get the number of threads still not joined in this process.
int set_current_thread_name(std::string const &name)
Set the name of the currently running thread.
int set_thread_name(pid_t tid, std::string const &name)
Set the name of the specified thread.
process_ids_t get_thread_ids(pid_t pid)
Retrieve the list of threads for a given process.
bool is_using_vdso()
Certain functions may be implemented using the vDSO library.
pid_t get_pid_max()
Get the maximum process identifier.
int get_total_number_of_processors()
Retrieve the number of processors available on this system.
std::string get_boot_id()
Retrieve the boot UUID.
std::string get_thread_name(pid_t tid)
Retrieve the name of a thread.
int get_number_of_available_processors()
Retrieve the number of processors currently usable.
std::string get_current_thread_name()
Retrieve the name of the current thread.
Thread Runner and Managers.
std::vector< pid_t > process_ids_t
A list of identifiers representing various processes.
constexpr pid_t PID_UNDEFINED
The value a PID variable is set to when not representing a process.