Skip to content

Commit

Permalink
bfstd: New sysoption() macro to check for POSIX option runtime support
Browse files Browse the repository at this point in the history
POSIX allows optional features to be supported at compile time but not
necessarily at run time by defining _POSIX_OPTION to 0 and requiring
users to check sysconf(_SC_OPTION) > 0.  The new sysoption() macro
simplifies the check.

sighook() and bfs_spawn() now check for conditional runtime support for
the relevant POSIX options.
  • Loading branch information
tavianator committed Aug 10, 2024
1 parent baf9ee6 commit 1507cc2
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 39 deletions.
13 changes: 13 additions & 0 deletions src/bfstd.h
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,19 @@ int xstrtofflags(const char **str, unsigned long long *set, unsigned long long *
*/
long xsysconf(int name);

/**
* Check for a POSIX option[1] at runtime.
*
* [1]: https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap02.html#tag_02_01_06
*
* @param name
* The symbolic name of the POSIX option (e.g. SPAWN).
* @return
* The value of the option, either -1 or a date like 202405.
*/
#define sysoption(name) \
(_POSIX_##name == 0 ? xsysconf(_SC_##name) : _POSIX_##name)

#include <wchar.h>

/**
Expand Down
11 changes: 7 additions & 4 deletions src/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -1018,12 +1018,15 @@ bool eval_xtype(const struct bfs_expr *expr, struct bfs_eval *state) {
* clock_gettime() wrapper.
*/
static int eval_gettime(struct bfs_eval *state, struct timespec *ts) {
#if _POSIX_MONOTONIC_CLOCK > 0
int ret = clock_gettime(CLOCK_MONOTONIC, ts);
#else
int ret = clock_gettime(CLOCK_REALTIME, ts);
clockid_t clock = CLOCK_REALTIME;

#if defined(_POSIX_MONOTONIC_CLOCK) && _POSIX_MONOTONIC_CLOCK >= 0
if (sysoption(MONOTONIC_CLOCK) > 0) {
clock = CLOCK_MONOTONIC;
}
#endif

int ret = clock_gettime(clock, ts);
if (ret != 0) {
bfs_warning(state->ctx, "%pP: clock_gettime(): %s.\n", state->ftwbuf, errstr());
}
Expand Down
24 changes: 17 additions & 7 deletions src/sighook.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@
#include <stdlib.h>
#include <unistd.h>

#if _POSIX_SEMAPHORES > 0
#ifdef _POSIX_SEMAPHORES
# define BFS_POSIX_SEMAPHORES _POSIX_SEMAPHORES
#else
# define BFS_POSIX_SEMAPHORES (-1)
#endif

#if BFS_POSIX_SEMAPHORES >= 0
# include <semaphore.h>
#endif

Expand All @@ -42,7 +48,7 @@ struct arc {
/** The reference itself. */
void *ptr;

#if _POSIX_SEMAPHORES > 0
#if BFS_POSIX_SEMAPHORES >= 0
/** A semaphore for arc_wake(). */
sem_t sem;
/** sem_init() result. */
Expand All @@ -57,8 +63,12 @@ static void arc_init(struct arc *arc) {
atomic_init(&arc->refs, 0);
arc->ptr = NULL;

#if _POSIX_SEMAPHORES > 0
arc->sem_status = sem_init(&arc->sem, false, 0);
#if BFS_POSIX_SEMAPHORES >= 0
if (sysoption(SEMAPHORES) > 0) {
arc->sem_status = sem_init(&arc->sem, false, 0);
} else {
arc->sem_status = -1;
}
#endif
}

Expand Down Expand Up @@ -93,7 +103,7 @@ static void arc_put(struct arc *arc) {
size_t refs = fetch_sub(&arc->refs, 1, release);

if (refs == 1) {
#if _POSIX_SEMAPHORES > 0
#if BFS_POSIX_SEMAPHORES >= 0
if (arc->sem_status == 0 && sem_post(&arc->sem) != 0) {
abort();
}
Expand All @@ -103,7 +113,7 @@ static void arc_put(struct arc *arc) {

/** Wait on the semaphore. */
static int arc_sem_wait(struct arc *arc) {
#if _POSIX_SEMAPHORES > 0
#if BFS_POSIX_SEMAPHORES >= 0
if (arc->sem_status == 0) {
while (sem_wait(&arc->sem) != 0) {
bfs_everify(errno == EINTR, "sem_wait()");
Expand Down Expand Up @@ -146,7 +156,7 @@ done:;
static void arc_destroy(struct arc *arc) {
bfs_assert(arc_refs(arc) == 0);

#if _POSIX_SEMAPHORES > 0
#if BFS_POSIX_SEMAPHORES >= 0
if (arc->sem_status == 0) {
bfs_everify(sem_destroy(&arc->sem) == 0, "sem_destroy()");
}
Expand Down
65 changes: 39 additions & 26 deletions src/xspawn.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
# include <paths.h>
#endif

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
# include <spawn.h>
#endif

Expand Down Expand Up @@ -70,29 +70,42 @@ int bfs_spawn_init(struct bfs_spawn *ctx) {
ctx->flags = 0;
SLIST_INIT(ctx);

#if _POSIX_SPAWN > 0
ctx->flags |= BFS_SPAWN_USE_POSIX;
#if BFS_POSIX_SPAWN >= 0
if (sysoption(SPAWN) > 0) {
ctx->flags |= BFS_SPAWN_USE_POSIX;

errno = posix_spawn_file_actions_init(&ctx->actions);
if (errno != 0) {
return -1;
}
errno = posix_spawn_file_actions_init(&ctx->actions);
if (errno != 0) {
return -1;
}

errno = posix_spawnattr_init(&ctx->attr);
if (errno != 0) {
posix_spawn_file_actions_destroy(&ctx->actions);
return -1;
errno = posix_spawnattr_init(&ctx->attr);
if (errno != 0) {
posix_spawn_file_actions_destroy(&ctx->actions);
return -1;
}
}
#endif

return 0;
}

int bfs_spawn_destroy(struct bfs_spawn *ctx) {
#if _POSIX_SPAWN > 0
posix_spawnattr_destroy(&ctx->attr);
posix_spawn_file_actions_destroy(&ctx->actions);
/**
* Clear the BFS_SPAWN_USE_POSIX flag and free the attributes.
*/
static void bfs_spawn_clear_posix(struct bfs_spawn *ctx) {
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
ctx->flags &= ~BFS_SPAWN_USE_POSIX;

#if BFS_POSIX_SPAWN >= 0
posix_spawnattr_destroy(&ctx->attr);
posix_spawn_file_actions_destroy(&ctx->actions);
#endif
}
}

int bfs_spawn_destroy(struct bfs_spawn *ctx) {
bfs_spawn_clear_posix(ctx);

for_slist (struct bfs_spawn_action, action, ctx) {
free(action);
Expand All @@ -101,7 +114,7 @@ int bfs_spawn_destroy(struct bfs_spawn *ctx) {
return 0;
}

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
/** Set some posix_spawnattr flags. */
_maybe_unused
static int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) {
Expand All @@ -121,7 +134,7 @@ static int bfs_spawn_addflags(struct bfs_spawn *ctx, short flags) {

return 0;
}
#endif // _POSIX_SPAWN > 0
#endif

/** Allocate a spawn action. */
static struct bfs_spawn_action *bfs_spawn_action(enum bfs_spawn_op op) {
Expand All @@ -143,7 +156,7 @@ int bfs_spawn_addopen(struct bfs_spawn *ctx, int fd, const char *path, int flags
return -1;
}

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = posix_spawn_file_actions_addopen(&ctx->actions, fd, path, flags, mode);
if (errno != 0) {
Expand All @@ -167,7 +180,7 @@ int bfs_spawn_addclose(struct bfs_spawn *ctx, int fd) {
return -1;
}

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = posix_spawn_file_actions_addclose(&ctx->actions, fd);
if (errno != 0) {
Expand All @@ -188,7 +201,7 @@ int bfs_spawn_adddup2(struct bfs_spawn *ctx, int oldfd, int newfd) {
return -1;
}

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = posix_spawn_file_actions_adddup2(&ctx->actions, oldfd, newfd);
if (errno != 0) {
Expand Down Expand Up @@ -228,7 +241,7 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) {
# define BFS_POSIX_SPAWN_ADDFCHDIR posix_spawn_file_actions_addfchdir_np
#endif

#if _POSIX_SPAWN > 0 && defined(BFS_POSIX_SPAWN_ADDFCHDIR)
#if BFS_POSIX_SPAWN >= 0 && defined(BFS_POSIX_SPAWN_ADDFCHDIR)
if (ctx->flags & BFS_SPAWN_USE_POSIX) {
errno = BFS_POSIX_SPAWN_ADDFCHDIR(&ctx->actions, fd);
if (errno != 0) {
Expand All @@ -237,7 +250,7 @@ int bfs_spawn_addfchdir(struct bfs_spawn *ctx, int fd) {
}
}
#else
ctx->flags &= ~BFS_SPAWN_USE_POSIX;
bfs_spawn_clear_posix(ctx);
#endif

action->in_fd = fd;
Expand All @@ -261,7 +274,7 @@ int bfs_spawn_setrlimit(struct bfs_spawn *ctx, int resource, const struct rlimit
goto fail;
}
#else
ctx->flags &= ~BFS_SPAWN_USE_POSIX;
bfs_spawn_clear_posix(ctx);
#endif

action->resource = resource;
Expand Down Expand Up @@ -482,7 +495,7 @@ static int bfs_resolve_early(struct bfs_resolver *res, const char *exe, const st
return -1;
}

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0

/** bfs_spawn() implementation using posix_spawn(). */
static pid_t bfs_posix_spawn(struct bfs_resolver *res, const struct bfs_spawn *ctx, char **argv, char **envp) {
Expand Down Expand Up @@ -516,7 +529,7 @@ static bool bfs_use_posix_spawn(const struct bfs_resolver *res, const struct bfs
return true;
}

#endif // _POSIX_SPAWN > 0
#endif // BFS_POSIX_SPAWN >= 0

/** Actually exec() the new process. */
_noreturn
Expand Down Expand Up @@ -653,7 +666,7 @@ static pid_t bfs_fork_spawn(struct bfs_resolver *res, const struct bfs_spawn *ct

/** Call the right bfs_spawn() implementation. */
static pid_t bfs_spawn_impl(struct bfs_resolver *res, const struct bfs_spawn *ctx, char **argv, char **envp) {
#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
if (bfs_use_posix_spawn(res, ctx)) {
return bfs_posix_spawn(res, ctx, argv, envp);
}
Expand Down
10 changes: 8 additions & 2 deletions src/xspawn.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@
#include <sys/types.h>
#include <unistd.h>

#if _POSIX_SPAWN > 0
#ifdef _POSIX_SPAWN
# define BFS_POSIX_SPAWN _POSIX_SPAWN
#else
# define BFS_POSIX_SPAWN (-1)
#endif

#if BFS_POSIX_SPAWN >= 0
# include <spawn.h>
#endif

Expand All @@ -38,7 +44,7 @@ struct bfs_spawn {
struct bfs_spawn_action *head;
struct bfs_spawn_action **tail;

#if _POSIX_SPAWN > 0
#if BFS_POSIX_SPAWN >= 0
/** posix_spawn() context, for when we can use it. */
posix_spawn_file_actions_t actions;
posix_spawnattr_t attr;
Expand Down

0 comments on commit 1507cc2

Please sign in to comment.