17 #ifndef ZTH_OS_WINDOWS
18 # include <sys/types.h>
19 # include <sys/wait.h>
24 # include <crt_externs.h>
25 # define environ (*_NSGetEnviron())
30 #if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
31 static void sigchld_handler(
int );
37 #if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
38 # ifdef ZTH_USE_VALGRIND
40 if(!RUNNING_ON_VALGRIND)
43 struct sigaction sa = {};
44 sa.sa_handler = &sigchld_handler;
45 sigaction(SIGCHLD, &sa,
nullptr);
51 #ifdef ZTH_USE_PTHREAD
52 static void* worker_main(
void*
fiber)
68 #ifdef ZTH_USE_PTHREAD
72 zth_dbg(thread,
"[%s] starting new Worker", thread_id_str().c_str());
76 if((res =
fiber->setStackSize(stack)))
82 if((res = pthread_create(&t,
nullptr, &worker_main, (
void*)
fiber)))
96 int execlp(
char const* file,
char const* arg, ... )
105 char const* a = va_arg(args,
char const*);
110 char* argcopy = strdup(a);
119 }
catch(std::bad_alloc
const&) {
128 for(
size_t i = 0; i < argv.
size(); i++)
135 __attribute__((unused))
static cow_string thread_id_str() noexcept
143 #ifdef ZTH_OS_WINDOWS
144 (
unsigned int)_getpid()
146 (
unsigned int)getpid()
157 #if defined(ZTH_OS_WINDOWS) || defined(ZTH_OS_BAREMETAL)
161 zth_dbg(thread,
"[%s] execvp %s", thread_id_str().c_str(), file);
164 if((pid = fork()) == 0) {
166 execve(file, arg, environ);
171 }
else if(pid == -1) {
173 zth_dbg(thread,
"[%s] Could not fork(); %s", thread_id_str().c_str(),
181 #if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
182 static volatile sig_atomic_t sigchld_cleanup = 0;
184 static void sigchld_handler(
int )
192 #if !defined(ZTH_OS_WINDOWS) && !defined(ZTH_OS_BAREMETAL)
193 # ifdef ZTH_USE_VALGRIND
195 if(!RUNNING_ON_VALGRIND)
197 if(
likely(sigchld_cleanup == 0))
201 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);
static safe_ptr< singleton_type >::type instance() noexcept
Return the only instance of T within this thread.
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.
size_t size() const noexcept
Return the number of elements stored in the vector.
value_type * data() noexcept
Access the data array.
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 >::factory fiber(F f, char const *name=nullptr)
Create 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
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.
string format(char const *fmt,...)
Format like sprintf(), but save the result in an 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.