Updated Caught in Loop - Had to Kill It

This is an interesting edge case. The Updater got into a loop of trying to update, failing, repeat. It appeared to be a non-stop loop.

I think this is what happened. I brought my laptop home from work. While working with the Sqlite extension, I noticed I could not save to my C: drive. My whole C: drive was suddenly read-only, and attempts at making C: drive folders write enabled were failing. I assume this might be a security thing with work that I have yet to resolve.

I’m assuming that is the root cause of the updater loop. It is trying to update your product and is not allowed to write the C: drive.

I’ll let you know more on Monday when I can discuss this with infrastructure folks at work.

Grindstone is installed in your user’s local app data folder. This is intended by Microsoft to be writeable, and lots of apps would fail if it were not. Did you observe that updater was a in a loop, or perhaps that Grindstone is continuously updating? It may sound like a subtle distinction, but an important one for us.

The installer window opened with the cycler, cycle for a short while, then close. It would repeat this process repeatedly until I went into the task manager and stopped the installer and installer(2) task. I had to be quick. When I restarted Grindstone, it would went into that process again until killed with installer.

When I was able to removed the read only property on my personal folders, Grindstone updated as it should.

Alright. Sounds like we need to add a check in the updater to override the read-only flag being set on Grindstone 4’s app files before it tries to perform the update.

Alright, buddy. I just prefaced the code that starts applying the update with some additional logic which will make sure a read-only flag won’t bork the update process.

static void removeReadOnlyFlag(FileSystemInfo fileSystemEntry) =>
    fileSystemEntry.Attributes &= ~FileAttributes.ReadOnly;

static void makeWritable(DirectoryInfo directory)
{
    removeReadOnlyFlag(directory);
    foreach (var subDirectory in directory.GetDirectories())
        makeWritable(directory);
    foreach (var file in directory.GetFiles())
        removeReadOnlyFlag(file);
}

makeWritable(new DirectoryInfo(ExecutablePath));

var updateProcess = new Process();
updateProcess.StartInfo.FileName = TempUpdaterPath;
updateProcess.StartInfo.Arguments = $"\"{TempPackagePath}\"";
updateProcess.Start();
Current.Dispatcher.Invoke(() => Quit(overrideSetUserIdle: true));

Since this can only affect future updates after it is applied, we’re gonna hold on to it until we have some more changes to make. But, it will be in there in the future!