On 12/19/16 21:42, Peter Dimov wrote:
Andrey Semashev wrote:
I think, a process could also modify the system-wide PATH variable, at least on some Windows versions. IIRC, some installers (Visual Studio? Intel compiler? I can't remember) did that at some point. I don't know if that's the case now.
You need root for that.
But installers always execute as root on Windows, don't they? (I believe, the term is "with elevated privileges") The idea is that the user installed something that modified system PATH so that it can later be used to inject a malicious process into your application. Also, disabling UAC is a popular practice, I think. :p
The full path does not solve the problem of setting up environment for the process though. E.g. I don't have a way to drop privileges of root before executing addr2line.
Dropping privileges could perhaps work for addr2line which takes a filename rather than a PID but it wouldn't work for utilities that are PID-based such as atos. If the program is root, the utility would also need root in order to inspect its address space and locate the module based on the address. I think.
Aren't there capabilities that could be granted to the child process? If not, that is unfortunate. Not just because dropping privileges won't work on all platforms, but also because the user will have to depend on the library implementation details to know if it can work. I suppose, this can be somewhat mitigated in the backend reported if it is capable to decode the stacktrace with reduced privileges.
Security issues aside, there is also a matter of controlling the child process. What if it hangs? Or crashes? How does it affect the master application? What if the master crashes (i.e. how can you ensure you don't leave a zombie process)? What will you do if you exhaust the limit of running processes in the system (i.e. if the app itself is not able to spawn its processes because of a bunch of running addr2line)?
Very similar questions can be posed towards the current Windows implementation. There isn't that much of a difference between using a helper process and doing the same work in-process.
In case of COM, handling the out-of-process COM objects is Windows' job. The application itself need not handle surrogate processes running those objects, nor does it have to specify path to those process executables or the COM object's dll. You are quite right in that COM hides most of that complexity, and that answers many of the questions above.
In fact, if your process has just crashed, it's better to do the work from another process, because its memory would be intact.
That is true, but I reiterate that handling a crash (or a signal) is special enough to warrant a special solution. At this point performance doesn't really matter, and the host process is pretty much doomed anyway, so the issues affecting its survival are off the table. By the way, since we're discussing crash handling, I have to say that I'm currently using gdb for this purpose. The signal handler in my process does fork and exec gdb, which saves the backtraces of all threads of the application to a file. If compared to Boost.Stacktrace, this approach has significant benefits, such as that gdb loads debug symbols, if present on the system, and that it dumps all threads instead of just one. Of course, gdb is much heavier than Boost.Stacktrace, but still this is something that I'd like to be achievable with the library.
Then, there are performance implications of running a process for each function call.
That's what I tried to address with my API suggestions.
I don't think that fully solves the performance issue because it still executes a process per stacktrace entry. In my example with gdb above, all decoding is done in one process, and I have to wonder how Boost.Stacktrace doing the same amount of work would compare to that.