This is the mail archive of the
mailing list for the Cygwin project.
Re: Retrieving per-process environment block?
On Wed, Nov 30, 2016 at 11:43 AM, Corinna Vinschen
> Hi Erik,
> On Nov 29 14:26, Erik Bray wrote:
>> On Thu, Nov 17, 2016 at 3:00 PM, Corinna Vinschen
>> <email@example.com> wrote:
>> > On Nov 17 14:30, Erik Bray wrote:
>> >> Hi all,
>> >> For a quick bit of background, I'm working on porting the highly
>> >> useful psutil  Python library to Cygwin. This has proved an
>> >> interesting exercise, as much of the functionality of psutil works on
>> >> Cygwin through existing POSIX interfaces, and a handful of
>> >> Linux-specific interfaces as well. But there are some bits that
>> >> simply don't map at all.
>> >> The one I'm struggling with right now is retrieving Cygwin environment
>> >> variables for a process (under inspection--i.e. not listing a
>> >> process's environment from within that process which is obviously
>> >> trivial).
>> >> I've looked at every route I could conceive of but as far as I can
>> >> tell this is currently impossible. That's fine for now--I simply
>> >> disable that functionality in psutil. But it is unfortunate, though,
>> >> since the information is there.
>> >> There are a couple avenues I could see to this. The most "obvious"
>> >> (to me) being to implement /proc/<pid>/environ.
>> >> I would be willing to provide a patch for this if it would be
>> >> accepted. Is there some particular non-obvious hurdle to this that it
>> >> hasn't been implemented? Obviously there are security
>> >> implications--the /proc/<pid>/environ should only be readable to the
>> >> process's owner, but that is already within Cygwin's capabilities, and
>> >> works for other /proc files.
>> > Patch welcome. Implementing this should be fairly straightforward.
>> > The only hurdle is winsup/CONTRIBUTORS ;)
>> Thanks--I went to go work on this finally but it turns out not to be
>> straightforward after all, as the process's environment is not shared
>> in any way between processes.
>> I could do this, if each process kept a copy of its environment block
>> in shared memory, which would in turn have to be updated every time
>> the process's environment is updated. But I don't know what the
>> impact of that would be performance-wise.
> You're right, it's not *that* straightforward. I got carried away by
> the idea but didn't think this through when replying to you.
> So, how to implement this?
> We have two types of information in /proc/$PID, one is information
> readily available without having to contact the target process, the
> other information is local to the target process and we have to get the
> information with the target processes consent. Argc, argv pointers
> are in the second group.
> So how do we contact the other process to ask for information?
> We have a mechanism inside Cygwin to request info from another process.
> It's part of the signal handling and consists basically of two
> functions. The applicant calls _pinfo::commune_request(), this will
> send a request into the signal pipe of the target process, this in turn
> will call commune_process(), a callback function, within the target
> Have a look into an example:
> Start in fhandler_process.cc, function format_process_cmdline()
> which implements /proc/$PID/cmdline.
> It fetches the _pinfo pointer of the target process and calls
> _pinfo::cmdline (in pinfo.cc) checks if the target process is a
> native Windows process a Cygwin process, or if its itself.
> In the native Windows case, it opens a handle to the target process,
> fetches its RTL_USER_PROCESS_PARAMETERS block (function
> open_commune_proc_parms). and fetches the info from the target process
> by directly reading from its memory. If it's itself it just constructs
> the info as desired and returns. Boring.
> In the Cygwin case, it calls _pinfo::commune_request (PICOM_CMDLINE).
> PICOM_CMDLINE is defined in pinfo.h, together with other values for the
> commune requests. It send the request over the signal pipe to the
> target process.
> The target process receives the request and calls commune_process(). It
> checks what info is requested, prepares the info and send it back over
> over the signal pipe.
> The (waiting) _pinfo::commune_request fetches the info from the pipe and
> returns to _pinfo::cmdline, which in turn returns to format_process_cmdline().
> So, ultimately, just copy the functionality of format_process_cmdline,
> _pinfo::cmdline, as well as the handling of PICOM_CMDLINE in
> _pinfo::commune_request and commune_process and you're done.
Thank you for the detailed guidance on that--that all makes sense. I
feel silly for missing that--I was actually poking around to see if
there was already something like that in the source but missed it.
For some reason I thought the cmdline was just stored directly in the
pinfo object itself.
But I knew, considering how signals are handled, that there had to be
some communication channel between processes; I just didn't know how
to use it for general purposes. I just played around with it a bit
and I get the gist of how __SIGCOMMUNE works, etc. Very clever.
I can see what to do now--thanks.
Problem reports: http://cygwin.com/problems.html
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple