15# include <sys/types.h>
21# include <crt_externs.h>
22# define environ (*_NSGetEnviron())
27#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
28static void sigchld_handler(
int );
34#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
35# ifdef ZTH_USE_VALGRIND
37 if(!RUNNING_ON_VALGRIND)
40 struct sigaction sa = {};
41 sa.sa_handler = &sigchld_handler;
42 sigaction(SIGCHLD, &sa,
nullptr);
49static void* worker_main(
void* fiber)
69 zth_dbg(thread,
"[%s] starting new Worker", thread_id_str().c_str());
73 if((res =
fiber->setStackSize(stack)))
79 if((res = pthread_create(&t,
nullptr, &worker_main, (
void*)
fiber)))
93int execlp(
char const* file,
char const* arg, ... )
102 char const* a = va_arg(args,
char const*);
107 char* argcopy = strdup(a);
116 }
catch(std::bad_alloc
const&) {
125 for(
size_t i = 0; i < argv.
size(); i++)
132__attribute__((unused))
static cow_string thread_id_str() noexcept
134 Worker
const* w = Worker::instance();
141 (
unsigned int)_getpid()
143 (
unsigned int)getpid()
155#if defined(ZTH_OS_WINDOWS) || defined(ZTH_OS_BAREMETAL)
159 zth_dbg(thread,
"[%s] execvp %s", thread_id_str().c_str(), file);
164 execve(file, arg, environ);
169 }
else if(pid == -1) {
171 zth_dbg(thread,
"[%s] Could not fork(); %s", thread_id_str().c_str(),
179#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
181static volatile sig_atomic_t sigchld_cleanup = 0;
183static void sigchld_handler(
int )
191#if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
192# ifdef ZTH_USE_VALGRIND
194 if(!RUNNING_ON_VALGRIND)
196 if(
likely(sigchld_cleanup == 0))
199 Worker* w = Worker::instance();
200 char const* id_str = w ? w->
id_str() :
"?";
206 pid_t pid = waitpid(-1, &wstatus, WNOHANG);
211 }
else if(pid == -1) {
212 zth_dbg(worker,
"[%s] waitpid() failed; %s", id_str,
err(errno).c_str());
215 zth_dbg(worker,
"[%s] Child process %u terminated with exit code %d",
216 id_str, (
unsigned int)pid, wstatus);
virtual char const * id_str() const override
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.
int execvp(char const *file, char *const arg[])
Start an external program.
fiber_type< F >::factory fiber(F f, char const *name=nullptr)
Create a new fiber.
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
char const * banner() noexcept
Prints 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())
Put a syscall into the perf output.
#define likely(expr)
Marks the given expression to likely be evaluated to true.