Commit 1b12e9ec authored by Geoff Simmons's avatar Geoff Simmons

check() happens under a writer lock, get() under a reader lock.

There are too many troubling possibilities for races otherwise.

This also eliminates the arbitrary sleep time in the constructor.
parent 38ba508e
...@@ -43,7 +43,6 @@ ...@@ -43,7 +43,6 @@
#include "cache/cache.h" #include "cache/cache.h"
#include "vcl.h" #include "vcl.h"
#include "vtim.h"
#include "vcc_if.h" #include "vcc_if.h"
...@@ -54,7 +53,6 @@ ...@@ -54,7 +53,6 @@
snprintf((rdr)->errbuf, (rdr)->errlen, "vmod file failure: " fmt, \ snprintf((rdr)->errbuf, (rdr)->errlen, "vmod file failure: " fmt, \
__VA_ARGS__) __VA_ARGS__)
#define INIT_SLEEP_INTERVAL 0.001
#define ERRMSG_LEN 128 #define ERRMSG_LEN 128
#define NO_ERR ("No error") #define NO_ERR ("No error")
...@@ -76,12 +74,13 @@ struct file_info { ...@@ -76,12 +74,13 @@ struct file_info {
struct VPFX(file_reader) { struct VPFX(file_reader) {
unsigned magic; unsigned magic;
#define FILE_READER_MAGIC 0x08d18e5b #define FILE_READER_MAGIC 0x08d18e5b
timer_t timerid; pthread_rwlock_t lock;
struct file_info *info; struct file_info *info;
char *vcl_name;
char *addr; char *addr;
char *vcl_name;
char *errbuf; char *errbuf;
size_t errlen; size_t errlen;
timer_t timerid;
int flags; int flags;
}; };
...@@ -101,13 +100,15 @@ check(union sigval val) ...@@ -101,13 +100,15 @@ check(union sigval val)
AN(rdr->errbuf); AN(rdr->errbuf);
AN(info->path); AN(info->path);
AZ(pthread_rwlock_wrlock(&rdr->lock));
errno = 0; errno = 0;
if (stat(info->path, &st) != 0) { if (stat(info->path, &st) != 0) {
VERRMSG(rdr, "%s: cannot read info about %s: %s", rdr->vcl_name, VERRMSG(rdr, "%s: cannot read info about %s: %s", rdr->vcl_name,
info->path, vstrerror(errno)); info->path, vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf); VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR; rdr->flags |= RDR_ERROR;
return; goto out;
} }
if (!S_ISREG(st.st_mode)) { if (!S_ISREG(st.st_mode)) {
...@@ -115,7 +116,7 @@ check(union sigval val) ...@@ -115,7 +116,7 @@ check(union sigval val)
info->path); info->path);
VSL(SLT_Error, 0, rdr->errbuf); VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR; rdr->flags |= RDR_ERROR;
return; goto out;
} }
if ((rdr->flags & (RDR_INITIALIZED | RDR_MAPPED)) if ((rdr->flags & (RDR_INITIALIZED | RDR_MAPPED))
...@@ -123,7 +124,7 @@ check(union sigval val) ...@@ -123,7 +124,7 @@ check(union sigval val)
&& info->mtime.tv_nsec == st.st_mtim.tv_nsec && info->mtime.tv_nsec == st.st_mtim.tv_nsec
&& info->dev == st.st_dev && info->ino == st.st_ino) { && info->dev == st.st_dev && info->ino == st.st_ino) {
AN(rdr->addr); AN(rdr->addr);
return; goto out;
} }
if (rdr->flags & RDR_MAPPED) { if (rdr->flags & RDR_MAPPED) {
...@@ -133,7 +134,7 @@ check(union sigval val) ...@@ -133,7 +134,7 @@ check(union sigval val)
vstrerror(errno)); vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf); VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR; rdr->flags |= RDR_ERROR;
return; goto out;
} }
} }
rdr->flags &= ~RDR_MAPPED; rdr->flags &= ~RDR_MAPPED;
...@@ -144,7 +145,7 @@ check(union sigval val) ...@@ -144,7 +145,7 @@ check(union sigval val)
info->path, vstrerror(errno)); info->path, vstrerror(errno));
VSL(SLT_Error, 0, rdr->errbuf); VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR; rdr->flags |= RDR_ERROR;
return; goto out;
} }
/* /*
...@@ -163,7 +164,7 @@ check(union sigval val) ...@@ -163,7 +164,7 @@ check(union sigval val)
VSL(SLT_Error, 0, rdr->errbuf); VSL(SLT_Error, 0, rdr->errbuf);
rdr->flags |= RDR_ERROR; rdr->flags |= RDR_ERROR;
closefd(&fd); closefd(&fd);
return; goto out;
} }
closefd(&fd); closefd(&fd);
AN(addr); AN(addr);
...@@ -179,6 +180,9 @@ check(union sigval val) ...@@ -179,6 +180,9 @@ check(union sigval val)
rdr->flags &= ~RDR_ERROR; rdr->flags &= ~RDR_ERROR;
strcpy(rdr->errbuf, NO_ERR); strcpy(rdr->errbuf, NO_ERR);
rdr->flags |= RDR_INITIALIZED; rdr->flags |= RDR_INITIALIZED;
out:
AZ(pthread_rwlock_unlock(&rdr->lock));
return; return;
} }
...@@ -192,6 +196,7 @@ vmod_reader__init(VRT_CTX, struct VPFX(file_reader) **rdrp, ...@@ -192,6 +196,7 @@ vmod_reader__init(VRT_CTX, struct VPFX(file_reader) **rdrp,
struct sigevent sigev; struct sigevent sigev;
timer_t timerid; timer_t timerid;
struct itimerspec timerspec; struct itimerspec timerspec;
int flags;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
AN(rdrp); AN(rdrp);
...@@ -228,6 +233,13 @@ vmod_reader__init(VRT_CTX, struct VPFX(file_reader) **rdrp, ...@@ -228,6 +233,13 @@ vmod_reader__init(VRT_CTX, struct VPFX(file_reader) **rdrp,
return; return;
} }
errno = 0;
if (pthread_rwlock_init(&rdr->lock, NULL) != 0) {
VFAIL(ctx, "new %s: initializing lock: %s", vcl_name,
vstrerror(errno));
return;
}
rdr->errlen = ERRMSG_LEN + strlen(name) + strlen(vcl_name); rdr->errlen = ERRMSG_LEN + strlen(name) + strlen(vcl_name);
errno = 0; errno = 0;
rdr->errbuf = malloc(rdr->errlen); rdr->errbuf = malloc(rdr->errlen);
...@@ -275,8 +287,10 @@ vmod_reader__init(VRT_CTX, struct VPFX(file_reader) **rdrp, ...@@ -275,8 +287,10 @@ vmod_reader__init(VRT_CTX, struct VPFX(file_reader) **rdrp,
AZ(rdr->info->mtime.tv_nsec); AZ(rdr->info->mtime.tv_nsec);
AZ(rdr->flags & (RDR_INITIALIZED | RDR_ERROR)); AZ(rdr->flags & (RDR_INITIALIZED | RDR_ERROR));
do { do {
VTIM_sleep(INIT_SLEEP_INTERVAL); AZ(pthread_rwlock_wrlock(&rdr->lock));
} while ((rdr->flags & (RDR_INITIALIZED | RDR_ERROR)) == 0); flags = rdr->flags;
AZ(pthread_rwlock_unlock(&rdr->lock));
} while ((flags & (RDR_INITIALIZED | RDR_ERROR)) == 0);
if (rdr->flags & RDR_ERROR) { if (rdr->flags & RDR_ERROR) {
AN(strcmp(rdr->errbuf, NO_ERR)); AN(strcmp(rdr->errbuf, NO_ERR));
...@@ -339,18 +353,26 @@ vmod_reader__fini(struct VPFX(file_reader) **rdrp) ...@@ -339,18 +353,26 @@ vmod_reader__fini(struct VPFX(file_reader) **rdrp)
VCL_STRING VCL_STRING
vmod_reader_get(VRT_CTX, struct VPFX(file_reader) *rdr) vmod_reader_get(VRT_CTX, struct VPFX(file_reader) *rdr)
{ {
int flags;
VCL_STRING addr;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC); CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
CHECK_OBJ_NOTNULL(rdr, FILE_READER_MAGIC); CHECK_OBJ_NOTNULL(rdr, FILE_READER_MAGIC);
if ((rdr->flags & RDR_ERROR) == 0) { AZ(pthread_rwlock_rdlock(&rdr->lock));
AN(rdr->addr); flags = rdr->flags;
AN(rdr->flags & RDR_MAPPED); addr = rdr->addr;
return (rdr->addr); AZ(pthread_rwlock_unlock(&rdr->lock));
if (flags & RDR_ERROR) {
AN(strcmp(rdr->errbuf, NO_ERR));
VRT_fail(ctx, "%s.get(): %s", rdr->vcl_name, rdr->errbuf);
return (NULL);
} }
AN(strcmp(rdr->errbuf, NO_ERR)); AN(flags & RDR_MAPPED);
VRT_fail(ctx, "%s.get(): %s", rdr->vcl_name, rdr->errbuf); AN(addr);
return (NULL); return (addr);
} }
VCL_STRING VCL_STRING
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment