pulsar icon indicating copy to clipboard operation
pulsar copied to clipboard

PulsarNext: Filesystem changes within symlinked folders no longer detected on macOS

Open savetheclocktower opened this issue 9 months ago • 8 comments

Thanks in advance for your bug report!

  • [x] Have you reproduced issue in safe mode?
  • [x] Have you used the debugging guide to try to resolve the issue?
  • [x] Have you checked our FAQs to make sure your question isn't answered there?
  • [x] Have you checked to make sure your issue does not already exist?
  • [x] Have you checked you are on the latest release of Pulsar?

What happened?

A user on Discord reports that PulsarNext has regressed in its file-watching capabilities, and can no longer detect changes to files outside of Pulsar if those files are within symlinked folders.

Pulsar version

PulsarNext 1.126.2025032416-next

Which OS does this happen on?

🍎 macOS

OS details

both Ventura and Sequoia

Which CPU architecture are you running this on?

ARM64/AArch64

What steps are needed to reproduce this?

mkdir project
mkdir project/folder
ln -s folder project/folder_symlink
pulsar-next project

In Pulsar Tree View expand all project folders

mkdir project/folder/test

Now in Tree View new folder test appears in project/folder but not in project/folder_symlink

Additional Information:

This is interesting. It might actually be an issue with nsfw, since PulsarNext recently attempted to switch off of node-pathwatcher and onto Pulsar’s builtin, nsfw-based watchPath function. Might just be a configuration thing, since I'm sure we're not the first people with this use case in mind.

savetheclocktower avatar Mar 31 '25 17:03 savetheclocktower

Having trouble reproducing this myself, and my system is very similar to that of the reporter. I suspect the repro steps are more nuanced than what's written above, since the reporter is experiencing this in a messy real-world scenario.

I'll keep it open for now; hopefully we can pin down the exact scenarios under which it's happening.

savetheclocktower avatar Mar 31 '25 17:03 savetheclocktower

Just in case attaching screen recording: https://github.com/user-attachments/assets/a6802a0d-932d-4b41-b50a-3d93c6e9dd6b

sergeyoleynik avatar Mar 31 '25 18:03 sergeyoleynik

Yeah, those same steps fail to reproduce the issue for me.

Soon there'll be a new ARM64 release of PulsarNext for you to try, but I don't have any reason to believe this behavior changed.

tree-view used to use node-pathwatcher, but I switched it to watchPath as part of an effort to deprecate node-pathwatcher. (We don't want to maintain our own filesystem watcher.) watchPath uses nsfw internally; nsfw is widely used in the Node ecosystem, but it apparently doesn't support some symlinking scenarios.

This shouldn't end up mattering, though! Here's why:

  • node-pathwatcher didn't support recursive watching — meaning it could watch a directory, but only for changes to the directory's children. Meaning…
  • …each directory item in tree-view is responsible for monitoring its own children and sets up its own file-watcher for doing so.
  • This general architecture was preserved even when I switched over to watchPath.
  • watchPath sets up recursive watchers by default and tries very hard to reuse existing watchers, so it would be plausible for it to think “didn't we already set up a watcher on the parent? I should just be able to reuse that!” That would be disastrous if the child directory is symlinked. Except…
  • the watcher resolves symlinks early in the process! Since it would see the directory's real path on disk, it wouldn't think it could reuse an existing watcher. So everything should theoretically work.

But the fact that it works for me but not for @sergeyoleynik means I don't know whether this logic is sound. A couple things could be happening:

  • Despite what I wrote above, watchPath could be attempting to reuse a watcher that it shouldn't. (No theory yet on why it would only do this some of the time.)
  • Because these repro steps involve the real directory and the symlinked directory existing within the project, maybe the watcher is firing events, but the instance of Directory that manages the symlinked directory doesn't think it should reload. Maybe this code path isn't being hit, but it would pass if we checked this.realPath in filePathIsChildOfDirectory instead of this.path. (@sergeyoleynik, if you're handy in Chrome developer tools, you could set some breakpoints and test this out yourself.)

savetheclocktower avatar Mar 31 '25 19:03 savetheclocktower

@savetheclocktower Thank you very much, you was right. Everything starts to work as expected after i changed this.path to this.realPath in this line in debugger

Also there is one more file system issue. I have Apache/2.4.63 on my machine and local host website for development purposes. There is Apache log file in PulsarNext project folder and when Apache writes logs to this file, Pulsar not refreshing file contents in text editor. So i need to reopen this file each time to update logs. Maybe you have any ideas why this file not refreshing? 🙏

The strange thing is — if i update this file manually in any other text editor, PulsarNext works fine and in editor everything updates correctly.

sergeyoleynik avatar Apr 01 '25 07:04 sergeyoleynik

@savetheclocktower Thank you very much, you was right. Everything starts to work as expected after i changed this.path to this.realPath in this line in debugger

Fantastic! Still no idea why our machines behave differently, but I can make this change pretty easily.

Also there is one more file system issue. I have Apache/2.4.63 on my machine and local host website for development purposes. There is Apache log file in PulsarNext project folder and when Apache writes logs to this file, Pulsar not refreshing file contents in text editor. So i need to reopen this file each time to update logs. Maybe you have any ideas why this file not refreshing? 🙏

The strange thing is — if i update this file manually in any other text editor, PulsarNext works fine and in editor everything updates correctly.

This is a curious one. The core change detection in the editor still uses node-pathwatcher (I'm pretty sure). The old version of that library (still being used for Pulsar stable) uses an old BSD system called kqueue to detect filesystem events on macOS, but the rewritten version (used for PulsarNext) modernizes the file-watching approach and uses the standard FSEvents API. It wouldn't surprise me that behavior differences result from the change, but if anything I would've expected the new implementation to be more accurate.

This code is another candidate for conversion to watchPath/nsfw… but nsfw uses FSEvents on macOS just like we do!

@sergeyoleynik, if you've got an editor like VS Code installed, let me know if it keeps up to date on a log file when Apache writes updates. If VS Code can detect it, it ought to be within our capabilities to detect it as well.

savetheclocktower avatar Apr 01 '25 07:04 savetheclocktower

@savetheclocktower Yes, i've checked in VS Code just now, it updates Apache log file correctly without any issues 🤷‍♂️ Unfortunately i'm not so good in programming and i can't even find place in debugger where file update event listener is located to check what happens when Apache writes to file. I would be grateful if you give me any ideas — where to search 🥹

UPD: I did little investigation — fs.watch does not handle any event when those log files are changing. While fs.watchFile works fine

sergeyoleynik avatar Apr 01 '25 07:04 sergeyoleynik

@savetheclocktower Yes, i've checked in VS Code just now, it updates Apache log file correctly without any issues 🤷‍♂️ Unfortunately i'm not so good in programming and i can't even find place in debugger where file update event listener is located to check what happens when Apache writes to file. I would be grateful if you give me any ideas — where to search 🥹

UPD: I did little investigation — fs.watch does not handle any event when those log files are changing. While fs.watchFile works fine

Sorry I haven't been able to chase this down yet, but I haven't forgotten about it. I'll keep this ticket open as a reminder to fix that bug in tree-view.

I think the code that would detect file changes for your log file lives somewhere within the text-buffer package, but I can't be sure until I look for myself. And it would almost certainly still use node-pathwatcher to detect the file change.

savetheclocktower avatar Apr 08 '25 04:04 savetheclocktower

@savetheclocktower Thank you. I've tried to listen access.log require('pathwatcher').watch('access.log',(e)=>{console.log(e)}) and nothing happened when Apache wrote to log. When i edit access.log with any text editor, callback function is working. It seems like the problem in pathwatcher module

sergeyoleynik avatar Apr 10 '25 05:04 sergeyoleynik