New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fsnotify.Write is not catching updates on Mac #54

Closed
jimzhan opened this Issue Dec 13, 2014 · 9 comments

Comments

Projects
None yet
2 participants
@jimzhan

jimzhan commented Dec 13, 2014

if event.Op&fsnotify.Write == fsnotify.Write {
    log.Println("modified file:", event.Name)
}

Events trigged: RENAME -> CREATE -> CHMOD -> CHMOD -> CHMOD

The exact example is not catching the event after file updates.

@nathany

This comment has been minimized.

Show comment
Hide comment
@nathany

nathany Dec 13, 2014

Member

Hi @jimzhan. Thanks for the report. I need a little more info.

How are you writing to the file? Are you using a text editor #17 or touch?
Are you watching an individual file or he directory containing the file?
Thanks.

Member

nathany commented Dec 13, 2014

Hi @jimzhan. Thanks for the report. I need a little more info.

How are you writing to the file? Are you using a text editor #17 or touch?
Are you watching an individual file or he directory containing the file?
Thanks.

@jimzhan

This comment has been minimized.

Show comment
Hide comment
@jimzhan

jimzhan Dec 14, 2014

Hi @nathany & thanks for the quick response.

  • I was just adding some characters to an existing file
  • I was using VIM under iTerm2
  • I was watching its directory

Clearly the events were triggered but not in the suggested way to catch.

jimzhan commented Dec 14, 2014

Hi @nathany & thanks for the quick response.

  • I was just adding some characters to an existing file
  • I was using VIM under iTerm2
  • I was watching its directory

Clearly the events were triggered but not in the suggested way to catch.

@nathany

This comment has been minimized.

Show comment
Hide comment
@nathany

nathany Dec 14, 2014

Member

@jimzhan It's likely to do with "atomic saves" in VIM. See #17.

Member

nathany commented Dec 14, 2014

@jimzhan It's likely to do with "atomic saves" in VIM. See #17.

@jimzhan

This comment has been minimized.

Show comment
Hide comment
@jimzhan

jimzhan Dec 14, 2014

@nathany By going through these related issues along with several further test cases, I suppose the simple delay trick is the only solution for now?

jimzhan commented Dec 14, 2014

@nathany By going through these related issues along with several further test cases, I suppose the simple delay trick is the only solution for now?

@nathany

This comment has been minimized.

Show comment
Hide comment
@nathany

nathany Dec 15, 2014

Member

I'm not sure what the simple delay trick is? When I use fsnotify, I just treat Create and Write as the same.

Member

nathany commented Dec 15, 2014

I'm not sure what the simple delay trick is? When I use fsnotify, I just treat Create and Write as the same.

@jimzhan

This comment has been minimized.

Show comment
Hide comment
@jimzhan

jimzhan Dec 15, 2014

I've tested Create & Write as well & they can't catch Delete & Update, what I'm doing now is a silly simple trick:

    var delay <-chan time.Time
    for {
        select {
        case event := <-self.daemon.Events:
            if self.inWatchList(event) {
                delay = time.After(3 * time.Second)
            }

        case err := <-self.daemon.Errors:
            log.Fatalf("Failed to watch the application sources: %v", err)

        case <-delay:
            // restart the daemon watcher.
            self.watch()

            err = self.install()
            if !self.installed {
                continue
            }
            gorun <- true
        }
    }

Any other suggestion?

jimzhan commented Dec 15, 2014

I've tested Create & Write as well & they can't catch Delete & Update, what I'm doing now is a silly simple trick:

    var delay <-chan time.Time
    for {
        select {
        case event := <-self.daemon.Events:
            if self.inWatchList(event) {
                delay = time.After(3 * time.Second)
            }

        case err := <-self.daemon.Errors:
            log.Fatalf("Failed to watch the application sources: %v", err)

        case <-delay:
            // restart the daemon watcher.
            self.watch()

            err = self.install()
            if !self.installed {
                continue
            }
            gorun <- true
        }
    }

Any other suggestion?

@jimzhan

This comment has been minimized.

Show comment
Hide comment
@jimzhan

jimzhan Dec 15, 2014

A brief follow-up, by checking all Write, Create & Remove events, and also postpone a bits seems to be working now.

func (self *app) inWatchList(event fsnotify.Event) bool {
    var basename = filepath.Base(event.Name)

    if event.Op&fsnotify.Write == fsnotify.Write ||
        event.Op&fsnotify.Create == fsnotify.Create ||
        event.Op&fsnotify.Remove == fsnotify.Remove {
        // We only needs WatchList under write events.
        for _, pattern := range WatchList {
            matched, _ := filepath.Match(pattern, basename)
            if matched {
                return true
            }
        }
    }
    return false
}
    var delay <-chan time.Time
    for {
        select {
        case event := <-self.daemon.Events:
            if self.inWatchList(event) {
                delay = time.After(500 * time.Millisecond)
            }

        case err := <-self.daemon.Errors:
            log.Fatalf("Failed to watch the application sources: %v", err)

        case <-delay:
            // restart the daemon watcher.
            self.watch()

            err = self.install()
            if !self.installed {
                continue
            }
            gorun <- true
        }
    }

I hope there'll be a better solution shipped with fsnotify, but this is by far the most stable one I've tested.

jimzhan commented Dec 15, 2014

A brief follow-up, by checking all Write, Create & Remove events, and also postpone a bits seems to be working now.

func (self *app) inWatchList(event fsnotify.Event) bool {
    var basename = filepath.Base(event.Name)

    if event.Op&fsnotify.Write == fsnotify.Write ||
        event.Op&fsnotify.Create == fsnotify.Create ||
        event.Op&fsnotify.Remove == fsnotify.Remove {
        // We only needs WatchList under write events.
        for _, pattern := range WatchList {
            matched, _ := filepath.Match(pattern, basename)
            if matched {
                return true
            }
        }
    }
    return false
}
    var delay <-chan time.Time
    for {
        select {
        case event := <-self.daemon.Events:
            if self.inWatchList(event) {
                delay = time.After(500 * time.Millisecond)
            }

        case err := <-self.daemon.Errors:
            log.Fatalf("Failed to watch the application sources: %v", err)

        case <-delay:
            // restart the daemon watcher.
            self.watch()

            err = self.install()
            if !self.installed {
                continue
            }
            gorun <- true
        }
    }

I hope there'll be a better solution shipped with fsnotify, but this is by far the most stable one I've tested.

@nathany

This comment has been minimized.

Show comment
Hide comment
@nathany

nathany Dec 15, 2014

Member

Thanks for following up.

Member

nathany commented Dec 15, 2014

Thanks for following up.

@nathany

This comment has been minimized.

Show comment
Hide comment
@nathany

nathany Feb 7, 2015

Member

Yah, it would be nice. But unfortunately that's more to do with how the underlying event monitoring systems work and how editors save files than with fsnotify.

Member

nathany commented Feb 7, 2015

Yah, it would be nice. But unfortunately that's more to do with how the underlying event monitoring systems work and how editors save files than with fsnotify.

@nathany nathany closed this Feb 7, 2015

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment