commit b8b26c5aa46c929fd4b0d785ace5ad1b92526c85
parent d80e2180795c3ce4ec5c687e08388b601678acb8
Author: leitner <leitner>
Date: Tue, 28 Oct 2014 13:55:12 +0000
add workaround for inotify race
Diffstat:
2 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/ftrigger.1 b/ftrigger.1
@@ -41,6 +41,10 @@ the watch on the file, ftrigger will never get notified. In practice, I
have only seen this happen with touch, where the open(3) is immediately
followed by the close(3), and there is no write(3) in the middle.
+To work around this race, ftrigger will also watch for modify events for
+the file, and if there aren't any within a second, it will assume the
+race happened and trigger on the file.
+
.SH AUTHOR
ftrigger was written by Felix von Leitner and can be downloaded from
.I http://www.fefe.de/minit/
diff --git a/ftrigger.c b/ftrigger.c
@@ -15,7 +15,8 @@ struct trigger {
const char* filename,* command;
char* dironly,* fileonly;
struct stat ss;
- int idd,idf; /* inotify-deskriptor */
+ int idd,idf,created; /* inotify-deskriptor */
+ /* created = 1: got a create event on the dir, added a watch on the file, but no modify events on the file yet */
}* root;
int n;
@@ -78,9 +79,10 @@ int main(int argc,char* argv[]) {
buffer_putmflush(buffer_2,"warning: could not stat file \"",root[i].filename,"\": ",strerror(errno),"\n");
else
root[i].idf=inotify_add_watch(in,root[i].filename,
- IN_CLOSE_WRITE|IN_MOVE_SELF|IN_DELETE_SELF);
+ IN_CLOSE_WRITE|IN_MOVE_SELF|IN_DELETE_SELF|IN_MODIFY);
root[i].idd=inotify_add_watch(in,root[i].dironly,
IN_MOVED_TO|IN_CREATE);
+ root[i].created=0;
}
p.fd=in;
@@ -96,7 +98,18 @@ again:
break;
}
return 1;
- case 0: continue;
+ case 0:
+ {
+ int foundone=0;
+ for (i=0; i<n; ++i)
+ if (root[i].created==1) {
+ memset(&root[i].ss,0,sizeof(root[i].ss));
+ root[i].created=0;
+ foundone=1;
+ }
+ if (foundone) goto goodevent;
+ }
+ continue;
case 1: break;
};
read(in,buf,sizeof(buf));
@@ -139,6 +152,12 @@ again:
for (i=0; i<n; ++i) {
if (root[i].idf==ie->wd) {
+ if (ie->mask & IN_MODIFY) {
+ root[i].created=0;
+ root[i].idf=inotify_add_watch(in,root[i].filename,
+ IN_CLOSE_WRITE|IN_MOVE_SELF|IN_DELETE_SELF);
+ continue;
+ }
if (ie->mask & (IN_DELETE_SELF|IN_MOVE_SELF)) {
#if 0
buffer_putmflush(buffer_1,root[i].filename," was ",
@@ -159,7 +178,8 @@ again:
if (root[i].idf!=-1)
inotify_rm_watch(in,root[i].idf);
root[i].idf=inotify_add_watch(in,root[i].filename,
- IN_CLOSE_WRITE|IN_MOVE_SELF|IN_DELETE_SELF);
+ IN_CLOSE_WRITE|IN_MOVE_SELF|IN_DELETE_SELF|IN_MODIFY);
+ root[i].created=1;
/* if the file was created, it will be empty now, wait for
* the IN_CLOSE_WRITE event. */
if (ie->mask & IN_CREATE) {