Is `Dir.pwd` broken in SU 2019.3 by Mac OS Catalina?

I have a client who reported a bug in one of my plugins which we tracked down to erratic behaviour of the Dir.pwd method. He reports this started happening after ‘upgrading’ to Catalina. He has since upgraded to Catalina 10.15.2 and SU 2019.3, but the problem still persists.

Dir.pwd is arbitrarily returning the expected value or an error.

> Dir.pwd
/Users/<user>/Documents

> Dir.pwd
Error: #<Errno::ENOENT: No such file or directory - getcwd>
<main>:in `pwd'
<main>:in `<main>'
SketchUp:1:in `eval'

At one time SketchUp was setting the working directory at startup to something else (which we devs didn’t feel was appropriate.) We complained and we all discussed it and it was decided that for safety, SketchUp would initially set the working directory to the user’s documents folder. (Beware that on Windows the name of this folder is localized into the system language.)

That said, … it is proper etiquette for a developer to return the working directory to the previous path after their code is done if they changed it. However you can not rely upon other extensions and plugins, or even the user not restoring the previous working directory. So either your code should use absolute paths, or temporarily change the working directory thus …

Dir.chdir(temporary_path) do
  # Use paths here relative to current working directory which is temporary_path
end
# Previous working directory automatically restored

So, in reality, you can only expect a certain working directory when your code changes it.
And therefore your code would likely not ever need to use Dir.pwd or Dir.getwd (which I prefer when I use it at the console.) Ie, it would not hurt for you to change dir to the same as the current working directory. Just use the block form of Dir.chdir.

Dir.chdir("~/Documents") do
  # Use paths here relative to user's Documents directory
end

It could be Catalina broke it. It looks like “getcwd” is the unixlike C function name …

Why it is trying to find a file of that name is weird.

That is exactly why Dir.pwd is there in my use case, to get the current value in order to restore it afterwards. I’m not relying on any previous values.
However I wasn’t aware of the temporary effect of the block form of Dir.chdir, that seems a more robust solution, thanks for that.

1 Like

:+1:

Class: Dir (Ruby 2.5.5)

If a block is given, it is passed the name of the new current directory, and the block is executed with that as the current directory. The original working directory is restored when the block exits. The return value of chdir is the value of the block. chdir blocks can be nested, but in a multi-threaded program an error will be raised if a thread attempts to open a chdir block while another thread has one open.

Can you elaborate on the steps to reproduce what you observe?

Hi Thom,
Just typing Dir.pwd in the Ruby console on SU 2019 / Mac OS Catalina seems to exhibit the issue. According to the screenshot I was sent it arbitrarily returns a valid path or an error as above.
NB I can’t reproduce myself as I do not have (and do not want) Catalina installed.

I just received a followup, based on Dan’s suggestion, I asked him to try:
Dir.chdir("/Users/<username>/Desktop") do puts Dir.pwd end
which works fine on my system (Mac OS 10.13.6 / SU 2019.3)
but for him it still returned the error. I thought by ensuring that the working directory is set to a valid value it would stop the error, but this suggests something is going wrong in the pwd method

There is a possibility that heightened security in Catalina may be involved. When I try the snippet that @archidave gave, I get a popup asking whether I want to allow SketchUp to access my Desktop. If I grant permission, the snippet runs correctly. If the permission isn’t granted or has previously been denied, access will fail. I’m using SketchUp 2019.3 (19.3.252) on Catalina 10.15.2

1 Like

Interesting…
We tried creating a new folder to see if that would invoke a request to grant permission.

He reports the following 2 responses alternate, but no pop-up message:

> Dir.chdir("/Users/<username>/Documents/new_test_folder") do puts Dir.pwd end
Error: #<Errno::EPERM: Operation not permitted - getcwd>
<main>:in `pwd'
<main>:in `block in <main>'
<main>:in `chdir'
<main>:in `<main>'
SketchUp:1:in `eval'

> Dir.chdir("/Users/<username>/Documents/new_test_folder") do puts Dir.pwd end
Error: #<Errno::ENOENT: No such file or directory - getcwd>
<main>:in `chdir'
<main>:in `<main>'
SketchUp:1:in `eval'

but if he uses the Dutch folder path name for that same new folder, only this variant occurs:

> Dir.chdir("/gebruikers/<username>/Documenten/new_test_folder") do puts Dir.pwd end
Error: #<Errno::ENOENT: No such file or directory - getcwd>
<main>:in `chdir'
<main>:in `<main>'
SketchUp:1:in `eval' 

I wonder if the Dutch localisation is also throwing another variable into the mix… does anybody know how the file path localisation is working in Catalina, is the Dutch an alias to the English original or the other way around…?
Unfortunately I don’t have access to the machine in question so can’t look ‘under the hood’.

Same here. I’ve asked my colleagues with access to Catalina machines to test this out.

thanks

UPDATE:
My client reports:

I realized that after upgrading, Catalina asks at first use of every app for permission to access the documents folder.
I did not remember I was asked to do it with Sketchup.

So I manually provided the permission in System Preferences > Security & Privacy > Privacy > Files & Folders tab by permitting Sketchup access to the documents folder. And that works :slight_smile:

How to Give System Permissions for Apps on MacOS Catalina

So he is at least able to use the plugin again.

But it still remains, how should this be handled by Ruby if permission is denied, and why is Dir.pwd giving inconsistent results? - that still doesn’t seem right.

In your report above, if you look closely, the first error (Errno::EPERM) is a permissions error that was raised in Ruby’s Dir.pwd method. The second error (Errno::ENOENT) is a no [directory] entry error that was raised in the Dir.chdir method. So there are two places in the Ruby Core that need “some love”.

Well there are really two facets here with this situation.

  1. How should the Ruby Core handle it? (Is it handled correctly now?)
  2. How should coders (SketchUp plugins in our case) handle this situation?

A(1) The raising of the Errno::EPERM permissions exception is the right thing to do by the Ruby Core.
But it should have been done first by Dir.chdir before Dir.pwd was called from within it’s block.
1a. Personally, I would argue that Dir.pwd should just spit out the working directory path regardless of security accessibility, and the permissions exception should not get raised until an actual permissions violation occurs (in this case an attempt to change the wd to the “secure” Documents directory.)

A(2) It is the coders responsibility to trap for the Errno::EPERM permissions exception within a rescue clause and provide a graceful bailout, and notify the user, say via a messagebox.
You have found that a coder can successfully test for access permission to the Documents directory folders via a call to Dir.chdir.

def documents_folder_accessible?
  Dir.chdir("~/Documents") { Dir.pwd; true }
rescue Errno::EPERM, Errno::ENOENT
  return false
end

ADD: MS Windows doesn’t automatically expand paths so this might be better for cross-platform …

def documents_folder_accessible?
  Dir.chdir(File.expand_path("~/Documents")) { Dir.pwd; true }
rescue Errno::EPERM, Errno::ENOENT => e
  puts e.inspect
  return false
end

Ruby’s File class also has some test methods. These have given mixed results for Windows platform in the past, but may work better on macOS.
File.readable?
File.readable_real?
File.writable?
File.writable_real?


It looks like some changes may need to be done in the Ruby Core, but this is not something Trimble can do. Thomas has filed bug reports for the Ruby Core in the past so he might be able to do so concerning this (if none have yet been filed.) The Ruby Core has it’s own website for filing an debate on issues.

Even if the Ruby Core backports macOS permissions fixes to 2.5 Ruby, it is not likely Trimble would recompile and re-release any SketchUp version other than the current version supporting Catalina. But this would only happen if a maintenance release was forthcoming.
As it’s very late in the year and the next major version is due, more than likely any fix for SU2019 will not happen.

this may be another reason to avoid ever changing pwd on mac…

Catalina seems to default to having your desktop and documents folders being on your iCloud Drive.

john

or another reason to never upgrade to Catalina :wink:
Dave