Retrieving per-process environment block?

Erik Bray erik.m.bray@gmail.com
Wed Nov 30 14:49:00 GMT 2016


On Wed, Nov 30, 2016 at 11:43 AM, Corinna Vinschen
<corinna-cygwin@cygwin.com> wrote:
> Hi Erik,
>
> On Nov 29 14:26, Erik Bray wrote:
>> On Thu, Nov 17, 2016 at 3:00 PM, Corinna Vinschen
>> <corinna-cygwin@cygwin.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 [1] 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
> process.
>
> 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.
>
> _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.

Hi Corinna,

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.

Erik

--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple



More information about the Cygwin mailing list