-
-
Notifications
You must be signed in to change notification settings - Fork 21.9k
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
unbreak OS_Unix::get_executable_path() on OpenBSD #61540
base: master
Are you sure you want to change the base?
Conversation
it's a maintainance release, see the announcement: https://godotengine.org/article/maintenance-release-godot-3-4-5 While here regen patches and add links to upstream PRs: - "unbreak OS_Unix::get_executable_path() on OpenBSD" godotengine/godot#61540 - "add OpenBSD support" RenderKit/embree#379
The aim of this method is to return an absolute path to the executable AFAIK. Falling back to |
#elif defined(__OpenBSD__) || defined(__NetBSD__) | ||
char resolved_path[MAXPATHLEN]; | ||
|
||
realpath(OS::get_executable_path().utf8().get_data(), resolved_path); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like there's no API for it, so I guess we should check if realpath(argv[0])
exist and if it's not also check in the PATH
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the reference: ziglang/zig#6718
OpenBSD doesn't provide a syscall to retrieve the path to the executable intentionally. I think that semarie@ reply in ziglang/zig#6718 (comment) explains better that I ever could why something like this is not wanted on OpenBSD. I'd avoid doing So no, I think that just |
|
Ah! I failed to notice that it was used not only for Anyway, for the scope of the OpenBSD port all of this it's not a real issue, i'll change the patch to hardcode the binary location as it was done before and, since it's a small patch, it's not a burden to maintain locally. I was a bit worried of folks that may want to hack on Godot on OpenBSD outside of the port tree however. Otherwise, I could re-work it to inspect argv[0] and if it looks like a path and realpath likes it return that, walk $PATH otherwise. It's not pretty, but hey, it's not possible to do better on UNIX AFAIK :) |
It is possible to set absolute path in the GDExtenson config, but it's usually relative. Executable path is one of the locations the engine is searching for lib if path is relative (it's a current directory, executable path, and executable path + "../lib"). So non-working Self-contained mode assumes the executable can be located anywhere, all configs, etc. are stored in the same folder as the executable (and this folder can be freely relocated). |
OK, so I guess the quickest option is to look at argv[0] and see if we can deduct a working path from it. ugly, racy, but don't see other way around :) will look into it tomorrow and update the PR :) |
9fc5dda
to
6542a91
Compare
Sorry, it took a while to fix this because of other complications in building godot from the master branch on OpenBSD. I've updated the PR to do what suggested, if |
(and possibly also on NetBSD) We can't do a realpath(3) on argv[0] (what OS::get_executable_path returns) because argv[0] is not guaranteed to be a path. Instead, search the executable in $PATH if argv[0] doesn't look like an absolute (or relative) path.
6542a91
to
2ae7135
Compare
Might I suggest this? Get the executable of an arbitrary PID on OpenBSD? (Not sure if Godot actually needs this for anything): Or if you just need for the current executable, this might help things a bit as well for less failure cases: |
I think the way to do this in a portable way is something like: #include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
long get_pathmax(void) {
long pathmax = -1;
errno = 0;
pathmax = pathconf("/", _PC_PATH_MAX);
if (-1 == pathmax) {
if (0 == errno) {
pathmax = PATH_MAX;
} else {
fprintf (stderr, "pathconf() FAILED, %d, %s\n", errno, strerror(errno));
}
}
return pathmax;
}
int main(int argc, char* argv[]) {
char* fullpath = malloc(get_pathmax());
char* cwd = getcwd(NULL, get_pathmax());
if (!cwd) {
fprintf (stderr, "getcwd() FAILED, %d, %s\n", errno, strerror(errno));
}
if (argv[0][0] == '/') {
strncpy(fullpath, argv[0], get_pathmax());
} else {
strncpy(fullpath, cwd, get_pathmax());
strncat(fullpath, "/", get_pathmax());
strncat(fullpath, argv[0], get_pathmax());
}
char* fullpath_canonical = realpath(fullpath, NULL);
printf("full path = %s\n", fullpath_canonical);
free(cwd);
free(fullpath);
free(fullpath_canonical);
} this would go in our unix main() function, and we'd have to store fullpath_canonical on the OS:: singleton somewhere I think. Example output:
Note that this might still require us to do something to actually get a directory rather than the path to the full executable, but that would be a simple matter of adding appropriate |
This seems reasonable, but it's possible that I might be missing some BSD specific aspects. |
@hpvb nope, that's wrong. Ignoring the issues with
In the first case, where The shell in the example was OpenBSD' ksh, but with bash it's the same story:
So, I still think that something like my PR where we walk |
I think my example is still the most bullet proof solution, even if it still does have failure cases. It will allow you to check the exact ino_t/dev_t numbers and see if they match up with an existing hardlink to the executable, and this will give improper results if more than one hardlink to the exe exists, though very unlikely people would create multiple hardlinks to a game executable. If you really wanted to, you could check if the number of hardlinks is greater than one, in which case the function could either fail or print a warning to console. I gave a very robust solution which works with every running process of a vanilla install of OpenBSD + Xenocara/Xorg. Not sure why my comment has been seemingly disregarded/ignored. I can provide a more stripped down reproducible for testing if you still aren't convinced. i.e. run the following from your OpenBSD terminal and prepare to be amazed:
|
@time-killer-games I haven't ignored your suggestion, it's just that i filed the PR beforehand and would prefer if godot didn't link to libkvm just for this. Also, please note the BUGS section of kvm_open(3):
So, yeah, I wouldn't use libkvm for anything new, and especially in a program like godot where |
I got a second opinion from someone on the FreeBSD discord, and they said this:
...meaning there really was meant to be only one kvm_open* call/function but with the desire to improve the function's error semantics as well as to keep backwards compatibility they had no choice but to split it into two different functions. Perhaps you could contact the OpenBSD mailing list to get clarity on the matter. Even then, libkvm is a very small library and it is very easy to link to it. I had it and the other system dependencies it relies on all statically linked in xproc, (in the past). It wasn't hard to do that. It barely increased the file size at all. |
(and possibly also on NetBSD)
On the OpenBSD port, we've carried a local patch to hardcode the path to the godot binary for a long time. Recently, I had to revise it (since we're now building godot with and without tools enabled) and I'm wondering how the original code could have ever worked.
The current
OS_Unix::get_executable_path
re-usesOS::get_executable_path
(which in turns isargv[0]
), does a realpath(3) on it and return the resolved string. This basically only works whenargv[0]
is an absolute path and fails badly when Godot is invoked asgodot
, for e.g. from the shell. Why don't just re-useargv[0]
as in the default implementation?