Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Tupfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ endif
ifneq ($(TARGET),win32)
client_objs += src/tup/vardict.o
client_objs += src/tup/send_event.o
ifeq ($(TARGET),macosx)
client_objs += src/tup/flock/flock.o
else
client_objs += src/tup/flock/fcntl.o
endif
: $(client_objs) |> !ar |> libtup_client.a
: src/tup/vardict.h |> !cp |> tup_client.h
endif
Expand Down
8 changes: 7 additions & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ case "$os" in
default_server=fuse3
monitor=inotify.c
;;
Darwin)
monitor=fsevents.c
;;
esac

server=${TUP_SERVER:-$default_server}
Expand Down Expand Up @@ -44,9 +47,11 @@ case "$os" in
plat_cflags="$plat_cflags -D_REENTRANT"
;;
Darwin)
flock_backend=flock
plat_files="$plat_files ../src/compat/dummy.c"
plat_files="$plat_files ../src/compat/clearenv.c "
plat_cflags="$plat_cflags -include ../src/compat/macosx.h"
plat_ldflags="$plat_ldflags -framework CoreServices"
default_cc=clang
;;
FreeBSD)
Expand All @@ -62,6 +67,7 @@ case "$os" in
;;
esac
: ${CC:=$default_cc}
: ${flock_backend:=fcntl}

rm -rf build
echo " mkdir build"
Expand All @@ -87,7 +93,7 @@ CFLAGS="$CFLAGS -DTUP_SERVER=\"$server\""
CFLAGS="$CFLAGS -DPCRE2_CODE_UNIT_WIDTH=8"
CFLAGS="$CFLAGS -DHAVE_CONFIG_H"

for i in ../src/tup/*.c ../src/tup/tup/main.c ../src/tup/monitor/$monitor ../src/tup/flock/fcntl.c ../src/inih/ini.c ../src/pcre/*.c $plat_files; do
for i in ../src/tup/*.c ../src/tup/tup/main.c ../src/tup/monitor/$monitor ../src/tup/monitor/common.c ../src/tup/flock/$flock_backend.c ../src/inih/ini.c ../src/pcre/*.c $plat_files; do
echo " bootstrap CC $CFLAGS $i"
# Put -I. first so we find our new luabuiltin.h file, not one built
# by a previous invocation of 'tup'.
Expand Down
2 changes: 2 additions & 0 deletions macosx.tup
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ CFLAGS += -include compat/macosx.h
TUP_SUID_GROUP = wheel

TUP_SERVER = fuse
TUP_MONITOR = fsevents
LDFLAGS += -framework CoreServices
4 changes: 4 additions & 0 deletions src/tup/flock/Tupfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
include_rules

ifneq ($(TARGET),win32)
ifeq ($(TARGET),macosx)
Comment thread
LoganDark marked this conversation as resolved.
Outdated
: foreach flock.c |> !cc |>
else
: foreach fcntl.c |> !cc |>
endif
else
: foreach lock_file.c |> !cc |>
endif
95 changes: 95 additions & 0 deletions src/tup/flock/flock.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/* vim: set ts=8 sw=8 sts=8 noet tw=78:
*
* tup - A file-based build system
*
* Copyright (C) 2011-2026 Mike Shal <marfey@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

/* BSD flock(2) backend. Used on macOS because kqueue EVFILT_VNODE with
* NOTE_FUNLOCK can detect flock releases (but not fcntl lock releases),
* enabling event-driven lock coordination in the monitor.
*/

#define _ATFILE_SOURCE
#include "tup/flock.h"
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <sys/file.h>

int tup_lock_open(int basefd, const char *lockname, tup_lock_t *lock)
{
int fd;

fd = openat(basefd, lockname, O_RDWR | O_CREAT, 0666);
if(fd < 0) {
perror(lockname);
fprintf(stderr, "tup error: Unable to open lockfile.\n");
return -1;
}
*lock = fd;
return 0;
}

void tup_lock_close(tup_lock_t lock)
{
if(close(lock) < 0) {
perror("close(lock)");
}
}

int tup_flock(tup_lock_t fd)
{
if(flock(fd, LOCK_EX) < 0) {
perror("flock LOCK_EX");
return -1;
}
return 0;
}

/* Returns: -1 error, 0 got lock, 1 would block */
int tup_try_flock(tup_lock_t fd)
{
if(flock(fd, LOCK_EX | LOCK_NB) < 0) {
if(errno == EWOULDBLOCK)
return 1;
perror("flock LOCK_EX|LOCK_NB");
return -1;
}
return 0;
}

int tup_unflock(tup_lock_t fd)
{
if(flock(fd, LOCK_UN) < 0) {
perror("flock LOCK_UN");
return -1;
}
return 0;
}

int tup_wait_flock(tup_lock_t fd)
{
/* Not used on macOS - the fsevents monitor uses kqueue
* NOTE_FUNLOCK/NOTE_ATTRIB for event-driven lock notification
* instead of polling. It is not possible to achieve this API on
* macOS without polling.
*/
(void)fd;
fprintf(stderr, "tup internal error: tup_wait_flock called on macOS\n");
return -1;
}
24 changes: 24 additions & 0 deletions src/tup/lock.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,30 @@ void tup_lock_closeall(void)
tup_lock_close(sh_lock);
}

int tup_lock_reopen(void)
{
/* After fork(), flock(2) locks are shared with the parent because
* they are per-file-description. Re-open the lock files to get
* independent file descriptions, then close the inherited ones.
* Open first so we never lack an fd for any lock file.
*/
tup_lock_t old_sh = sh_lock;
tup_lock_t old_obj = obj_lock;
tup_lock_t old_tri = tri_lock;

if(tup_lock_open(tup_top_fd(), TUP_SHARED_LOCK, &sh_lock) < 0)
return -1;
if(tup_lock_open(tup_top_fd(), TUP_OBJECT_LOCK, &obj_lock) < 0)
return -1;
if(tup_lock_open(tup_top_fd(), TUP_TRI_LOCK, &tri_lock) < 0)
return -1;

tup_lock_close(old_sh);
tup_lock_close(old_obj);
tup_lock_close(old_tri);
return 0;
}

tup_lock_t tup_sh_lock(void)
{
return sh_lock;
Expand Down
6 changes: 6 additions & 0 deletions src/tup/lock.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ void tup_lock_exit(void);
/** Just closes the locks. This should by called by any forked processes. */
void tup_lock_closeall(void);

/** Re-opens lock files after fork to get independent file descriptions.
* Required when using flock(2) because flock locks are per-file-description
* and are shared across fork.
*/
int tup_lock_reopen(void);

/* Tri-lock functions */
tup_lock_t tup_sh_lock(void);
tup_lock_t tup_obj_lock(void);
Expand Down
2 changes: 1 addition & 1 deletion src/tup/monitor/Tupfile
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
include_rules

: $(TUP_MONITOR).c |> !cc |>
: foreach $(TUP_MONITOR).c common.c |> !cc |>
Loading