15# include <sys/types.h>
21# include <crt_externs.h>
22# define environ (*_NSGetEnviron())
31safe_ptr<Worker>::type Worker::instance() noexcept
37#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
38static void sigchld_handler(
int );
44#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
45# ifdef ZTH_USE_VALGRIND
47 if(!RUNNING_ON_VALGRIND)
50 struct sigaction sa = {};
51 sa.sa_handler = &sigchld_handler;
52 sigaction(SIGCHLD, &sa,
nullptr);
59static void* worker_main(
void* fiber)
79 zth_dbg(thread,
"[%s] starting new Worker", thread_id_str().c_str());
83 if((res =
fiber->setStackSize(stack)))
89 if((res = pthread_create(&t,
nullptr, &worker_main, (
void*)
fiber)))
103int execlp(
char const* file,
char const* arg, ... )
112 char const* a = va_arg(args,
char const*);
117 char* argcopy = strdup(a);
126 }
catch(std::bad_alloc
const&) {
135 for(
size_t i = 0; i < argv.
size(); i++)
142__attribute__((unused))
static cow_string thread_id_str() noexcept
144 Worker
const* w = Worker::instance();
151 (
unsigned int)_getpid()
153 (
unsigned int)getpid()
165#if defined(ZTH_OS_WINDOWS) || defined(ZTH_OS_BAREMETAL)
169 zth_dbg(thread,
"[%s] execvp %s", thread_id_str().c_str(), file);
174 execve(file, arg, environ);
179 }
else if(pid == -1) {
181 zth_dbg(thread,
"[%s] Could not fork(); %s", thread_id_str().c_str(),
189#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
191static volatile sig_atomic_t sigchld_cleanup = 0;
193static void sigchld_handler(
int )
201#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
202# ifdef ZTH_USE_VALGRIND
204 if(!RUNNING_ON_VALGRIND)
206 if(
likely(sigchld_cleanup == 0))
209 Worker* w = Worker::instance();
210 char const* id_str = w ? w->
id_str() :
"?";
216 pid_t pid = waitpid(-1, &wstatus, WNOHANG);
221 }
else if(pid == -1) {
222 zth_dbg(worker,
"[%s] waitpid() failed; %s", id_str,
err(errno).c_str());
225 zth_dbg(worker,
"[%s] Child process %u terminated with exit code %d",
226 id_str, (
unsigned int)pid, wstatus);
virtual char const * id_str() const noexcept override
static safe_ptr< singleton_type >::type instance() noexcept
Return the only instance of T within this thread.
The class that manages the fibers within this thread.
void run(TimeInterval const &duration=TimeInterval())
A simple std::vector, which can contain Prealloc without heap allocation.
void push_back(value_type const &v)
Append an element to the vector using the copy constructor.
value_type * data() noexcept
Access the data array.
size_t size() const noexcept
Return the number of elements stored in the vector.
int startWorkerThread(void(*f)(), size_t stack=0, char const *name=nullptr)
Start a new thread, create a Worker, with one fiber, which executes f.
int execlp(char const *file, char const *arg,...)
Start an external program.
fiber_type< F >::fiber fiber(F &&f, Args &&... args)
Create and start a new fiber.
int execvp(char const *file, char *const arg[])
Start an external program.
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
char const * banner() noexcept
Returns a banner line with version and configuration information.
void worker_global_init()
string err(int e)
Return a string like strerror() does, but as a zth::string.
void perf_syscall(char const *syscall, Timestamp const &t=Timestamp()) noexcept
Put a syscall into the perf output.
#define likely(expr)
Marks the given expression to likely be evaluated to true.