Skip to content

Commit

Permalink
vere: use fcntl advisory locks on pidfile
Browse files Browse the repository at this point in the history
  • Loading branch information
joemfb committed Aug 6, 2024
1 parent 148219d commit e36ea43
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 56 deletions.
161 changes: 105 additions & 56 deletions pkg/vere/disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -833,86 +833,134 @@ _disk_lock(c3_c* pax_c)
return paf_c;
}

/* u3_disk_acquire(): acquire a lockfile, killing anything that holds it.
/* _disk_acquire(): acquire a lockfile, killing anything that holds it.
*/
static void
u3_disk_acquire(c3_c* pax_c)
static c3_i
_disk_acquire(c3_c* pax_c)
{
c3_c* paf_c = _disk_lock(pax_c);
c3_w pid_w;
FILE* loq_u;

if ( NULL != (loq_u = c3_fopen(paf_c, "r")) ) {
if ( 1 != fscanf(loq_u, "%" SCNu32, &pid_w) ) {
u3l_log("lockfile %s is corrupt!", paf_c);
kill(getpid(), SIGTERM);
sleep(1); u3_assert(0);
}
else if (pid_w != getpid()) {
c3_w i_w;
c3_c* paf_c = _disk_lock(pax_c);
c3_y dat_y[12] = {0};
c3_w pid_w = 0;
c3_i fid_i, ret_i;

if ( -1 == (fid_i = c3_open(paf_c, O_RDWR|O_CREAT, 0666)) ) {
fprintf(stderr, "disk: failed to open/create lock file\r\n");
goto fail;
}

int ret = kill(pid_w, SIGTERM);
{
c3_y len_y = 0;
c3_y* buf_y = dat_y;

do {
c3_zs ret_zs;

if ( -1 == (ret_zs = read(fid_i, buf_y, 1)) ) {
if ( EINTR == errno ) continue;

if ( -1 == ret && errno == EPERM ) {
u3l_log("disk: permission denied when trying to kill process %d!", pid_w);
kill(getpid(), SIGTERM);
sleep(1); u3_assert(0);
fprintf(stderr, "disk: failed to read lockfile: %s\r\n",
strerror(errno));
goto fail;
}

if ( -1 != ret ) {
u3l_log("disk: stopping process %d, live in %s...",
pid_w, pax_c);
if ( !ret_zs ) break;
else if ( 1 != ret_zs ) {
fprintf(stderr, "disk: strange lockfile read %zd\r\n", ret_zs);
goto fail;
}

for ( i_w = 0; i_w < 16; i_w++ ) {
sleep(1);
if ( -1 == kill(pid_w, SIGTERM) ) {
break;
}
}
if ( 16 == i_w ) {
for ( i_w = 0; i_w < 16; i_w++ ) {
if ( -1 == kill(pid_w, SIGKILL) ) {
break;
}
sleep(1);
}
}
if ( 16 == i_w ) {
u3l_log("disk: process %d seems unkillable!", pid_w);
u3_assert(0);
}
u3l_log("disk: stopped old process %u", pid_w);
len_y++;
buf_y++;
}
while ( len_y < sizeof(dat_y) );


if ( len_y ) {
if ( (1 != sscanf((c3_c*)dat_y, "%" SCNu32 "%n", &pid_w, &ret_i))
|| (0 >= ret_i)
|| ('\n' != *(dat_y + ret_i)) )
{
fprintf(stderr, "disk: lockfile is corrupt\r\n");
}
}
fclose(loq_u);
c3_unlink(paf_c);
}

if ( NULL == (loq_u = c3_fopen(paf_c, "w")) ) {
u3l_log("disk: unable to open %s: %s", paf_c, strerror(errno));
u3_assert(0);
{
struct flock lok_u;
memset((void *)&lok_u, 0, sizeof(lok_u));
lok_u.l_type = F_WRLCK;
lok_u.l_whence = SEEK_SET;
lok_u.l_start = 0;
lok_u.l_len = 1;

while ( (ret_i = fcntl(fid_i, F_SETLK, &lok_u))
&& (EINTR == (ret_i = errno)) );

if ( ret_i ) {
if ( pid_w ) {
fprintf(stderr, "pier: locked by PID %u\r\n", pid_w);
}
else {
fprintf(stderr, "pier: strange: locked by empty lockfile\r\n");
}

goto fail;
}
}

fprintf(loq_u, "%u\n", getpid());
ret_i = snprintf((c3_c*)dat_y, sizeof(dat_y), "%u\n", getpid());

if ( 0 >= ret_i ) {
fprintf(stderr, "disk: failed to write lockfile\r\n");
goto fail;
}

{
c3_i fid_i = fileno(loq_u);
c3_sync(fid_i);
c3_y len_y = (c3_y)ret_i;
c3_y* buf_y = dat_y;

do {
c3_zs ret_zs;

if ( (-1 == (ret_zs = write(fid_i, buf_y, len_y)))
&& (EINTR != errno) )
{
fprintf(stderr, "disk: lockfile write failed %s\r\n",
strerror(errno));
goto fail;
}

if ( 0 < ret_zs ) {
len_y -= ret_zs;
buf_y += ret_zs;
}
}
while ( len_y );
}

if ( -1 == c3_sync(fid_i) ) {
fprintf(stderr, "disk: failed to sync lockfile: %s\r\n",
strerror(errno));
goto fail;
}

fclose(loq_u);
c3_free(paf_c);
return fid_i;

fail:
kill(getpid(), SIGTERM);
sleep(1); u3_assert(0);
}

/* u3_disk_release(): release a lockfile.
/* _disk_release(): release a lockfile.
*/
static void
u3_disk_release(c3_c* pax_c)
_disk_release(c3_c* pax_c, c3_i fid_i)
{
c3_c* paf_c = _disk_lock(pax_c);

c3_unlink(paf_c);
c3_free(paf_c);
close(fid_i);
}

/* u3_disk_exit(): close the log.
Expand Down Expand Up @@ -959,7 +1007,7 @@ u3_disk_exit(u3_disk* log_u)
}
}

u3_disk_release(log_u->dir_u->pax_c);
_disk_release(log_u->dir_u->pax_c, log_u->lok_i);

u3_dire_free(log_u->dir_u);
u3_dire_free(log_u->urb_u);
Expand Down Expand Up @@ -1817,6 +1865,7 @@ u3_disk*
u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u)
{
u3_disk* log_u = c3_calloc(sizeof(*log_u));
log_u->lok_i = -1;
log_u->liv_o = c3n;
log_u->ted_o = c3n;
log_u->cb_u = cb_u;
Expand All @@ -1835,7 +1884,7 @@ u3_disk_init(c3_c* pax_c, u3_disk_cb cb_u)

// acquire lockfile.
//
u3_disk_acquire(pax_c);
log_u->lok_i = _disk_acquire(pax_c);

// create/load $pier/.urb
//
Expand Down
1 change: 1 addition & 0 deletions pkg/vere/vere.h
Original file line number Diff line number Diff line change
Expand Up @@ -553,6 +553,7 @@
u3_dire* dir_u; // main pier directory
u3_dire* urb_u; // urbit system data
u3_dire* com_u; // log directory
c3_i lok_i; // lockfile
c3_o liv_o; // live
c3_w ver_w; // version (see version.h)
void* mdb_u; // lmdb env of current epoch
Expand Down

0 comments on commit e36ea43

Please sign in to comment.