Since the first review, the author has made the following changes from the original proposal that were requested by the Language Steering Group:
The type of the property is now the standard library's FilePath type that was added in SE-0529.
The API now returns nil on platforms where there is currently no concept of the current executable path, instead of being conditionally unavailable in those configurations.
A diff of the changes in this version of the proposal can be seen here.
Reviews are an important part of the Swift evolution process. All review feedback should be either on this forum thread or, if you would like to keep your feedback private, directly to me as the review manager by DM. When contacting the review manager directly, please put "SE-0513" in the subject line.
What goes into a review?
The goal of the review process is to improve the proposal under review through constructive criticism and, eventually, determine the direction of Swift. When writing your review, here are some questions you might want to answer in your review:
What is your evaluation of the proposal?
Is the problem being addressed significant enough to warrant a change to Swift?
Does this proposal fit well with the feel and direction of Swift?
If you have used other languages or libraries with a similar feature, how do you feel that this proposal compares to those?
How much effort did you put into your review? A glance, a quick reading, or an in-depth study?
Hi Tony, do you have a link to the original request for revision handy? I think it would be helpful to understand what the LSG had to say about some of the design decisions that are related to the points on which feedback was requested.
If there is a symlink, its presence is not necessarily a problem for the calling code
I think this is missing an even stronger point in favor of not resolving symlinks: it is relatively common for a program to behave differently based on its name. For example, IIRC, if you name your GCC binary g++ it will parse C++ code, while if it is named gcc it will only parse C code. Most toolchains will therefore create a symlink from g++ to gcc. If this API were to automatically resolve symlinks, it would be impossible to build a program that behaves like this using the proposed API.
On platforms where this property cannot be implemented (generally because the underlying operating system does not provide an interface for querying the executable path), the value of this property is always nil.
Is there ever a case where this can be nil even if the platform normally supports providing this path?
On Darwin, the property can be back-deployed because it is implemented atop existing API provided by the operating system.
But what about the FilePath type? Will that be able to be back-deployed?
This is not accurate, and is the purpose of the proposal’s disclaimer about argv[0]. The functionality you describe is determined by what the calling process puts in argv[0]. You could hardlink or even copy g++ to gcc and still observe the same behavior on either binary, depending on what you put in your execve call.
There are platform-specific failure modes, yes. They're unavoidable edge cases, and a developer can't avoid them by writing their own implementation either.
From the proposal text:
If the path to the current executable could not be determined, the value of this property is nil.
This is covered by the FilePath proposal. Short answer: that's the plan.
Hm, then what are the use cases for this API then? I feel like if I was building a CLI like that I would naturally reach for this API. But that seems to be the wrong choice!
This question is discussed in the proposal and the previous review thread.
Some but not all of the reasons you might need the path to your executable:
You need to find files adjacent to it such as resources/assets
You need to spawn a new process using the same executable (fork() but, you know, not awful)
You chose to implement your "what is my process name and how do I behave?" logic in C/C++/etc. based on the path rather than argv[0] and are moving to Swift
Won’t this be subject to TOCTOU-style issues if the binary is replaced after launch?
The docs for this property should definitely include a discussion of when it should be used vs CommandLine.arguments[0]. Right now this seems really subtle.
I don’t think we need to re-litigate the usefulness of this API here. It has already been accepted, apart from the two changes under review here, and the underlying OS-specific mechanisms it wraps are in wide use.
There's always room for improving documentation. The exact wording of API documentation can be changed outside the SE process, so we can noodle on it after-the-fact.
Is there ever a case where this can be nil even if the platform normally supports providing this path?
Yes, as two examples (1) unlinking the filename between process launch and calling this API, and (2) starting the process and chroot’ing into a directory that no longer allows access to the original path (I assume this will fail as opposed to giving an incorrect answer).
As a bonus example you may be able to trigger this sort of state by sandboxing the process in a way that makes it impossible to reach the executable (or the directory it is in), but I don’t know exactly how the path is retrieved so this might not stop it from working. In theory you maybe be able to use normal Unix permissions (or ACLs) to create situation where you can execute the binary but not examine the directory it is in so that might also fail.
I’m sure there are other error cases, but those are the ones that spring to mind. None of them are going to be very common. Depending on how the API is implemented you might not get the name you expect if hard links are in the mix, especially if one of the hard links is inaccessible but the other is not.