From: Simon Marchi <simon.marchi@polymtl.ca>
To: Sergio Durigan Junior <sergiodj@redhat.com>
Cc: GDB Patches <gdb-patches@sourceware.org>,
Pedro Alves <palves@redhat.com>,
Eli Zaretskii <eliz@gnu.org>
Subject: Re: [PATCH v2] Implement the ability to set/unset environment variables to GDBserver when starting the inferior
Date: Sat, 29 Jul 2017 22:36:00 -0000 [thread overview]
Message-ID: <d9dae60ba5a7e1aca29f15fe865f4110@polymtl.ca> (raw)
In-Reply-To: <20170727033531.23066-1-sergiodj@redhat.com>
Hi Sergio,
I took a closer look at set/unset, I have a few comments.
> @@ -99,32 +107,104 @@ gdb_environ::get (const char *var) const
> void
> gdb_environ::set (const char *var, const char *value)
> {
> + char *fullvar = concat (var, "=", value, NULL);
> +
> /* We have to unset the variable in the vector if it exists. */
> - unset (var);
> + unset (var, false);
>
> /* Insert the element before the last one, which is always NULL. */
> - m_environ_vector.insert (m_environ_vector.end () - 1,
> - concat (var, "=", value, NULL));
> + m_environ_vector.insert (m_environ_vector.end () - 1, fullvar);
> +
> + /* Mark this environment variable as having been set by the user.
> + This will be useful when we deal with setting environment
> + variables on the remote target. */
> + m_user_set_env_list.push_back (fullvar);
> +
> + /* If this environment variable is marked as unset by the user, then
> + remove it from the list, because now the user wants to set
> + it. */
> + for (std::vector<const char *>::iterator iter_user_unset
> + = m_user_unset_env_list.begin ();
> + iter_user_unset != m_user_unset_env_list.end ();
> + ++iter_user_unset)
> + if (strcmp (var, *iter_user_unset) == 0)
> + {
> + void *v = (void *) *iter_user_unset;
> +
> + m_user_unset_env_list.erase (iter_user_unset);
> + xfree (v);
> + break;
> + }
> }
>
> /* See common/environ.h. */
>
> void
> -gdb_environ::unset (const char *var)
> +gdb_environ::unset (const char *var, bool update_unset_list)
> {
> size_t len = strlen (var);
> + std::vector<char *>::iterator it_env;
>
> /* We iterate until '.end () - 1' because the last element is
> always NULL. */
> - for (std::vector<char *>::iterator el = m_environ_vector.begin ();
> - el != m_environ_vector.end () - 1;
> - ++el)
> - if (match_var_in_string (*el, var, len))
> - {
> - xfree (*el);
> - m_environ_vector.erase (el);
> - break;
> - }
> + for (it_env = m_environ_vector.begin ();
> + it_env != m_environ_vector.end () - 1;
> + ++it_env)
> + if (match_var_in_string (*it_env, var, len))
> + break;
> +
> + if (it_env == m_environ_vector.end () - 1)
> + {
> + /* No element has been found. */
> + return;
> + }
Do we want to support the use case to unset an environment variable that
is defined on the remote system, but not on the local system? If so,
the function should probably not return immediately if the variable is
not found in the env vector, so that the unset request ends up in the
list of variables to unset.
> +
> + std::vector<const char *>::iterator it_user_set_env;
> + char *found_var = *it_env;
> +
> + it_user_set_env = std::remove (m_user_set_env_list.begin (),
> + m_user_set_env_list.end (),
> + found_var);
> + if (it_user_set_env != m_user_set_env_list.end ())
> + {
> + /* We found (and removed) the element from the user_set_env
> + vector. */
> + m_user_set_env_list.erase (it_user_set_env,
> m_user_set_env_list.end ());
> + }
> +
> + if (update_unset_list)
> + {
> + bool found_in_unset = false;
> +
> + for (const char *el : m_user_unset_env_list)
> + if (strcmp (el, var) == 0)
> + {
> + found_in_unset = true;
> + break;
> + }
> +
> + if (!found_in_unset)
> + m_user_unset_env_list.push_back (xstrdup (var));
> + }
> +
> + m_environ_vector.erase (it_env);
> + xfree (found_var);
> +}
I have the feeling that we can reduce the amount of boilerplate code in
the set and unset methods by using std::set instead of std::vector.
Performance-wise this may not be very good, since for any reasonable
amount of variables, the vector would probably be more efficient. But
its interface makes the code clearer and lighter, in my opinion. I
suppose we could always make something with a set-like interface and
behavior implemented on top of a vector.
> +
> +/* See common/environ.h. */
> +
> +void
> +gdb_environ::clear_user_set_env ()
> +{
> + std::vector<const char *> copy = m_user_set_env_list;
> +
> + for (const char *var : copy)
> + {
> + std::string varname (var);
> +
> + varname.erase (varname.find ('='), std::string::npos);
> + unset (varname.c_str (), false);
> + }
I am not sure having a method like this is correct. It is used in
gdbserver when we want to "reset" the environment, that is forget all
user-made modifications, both set and unset. To do it correctly, it
should include restoring the variables that have been unset or
overwritten. But as I said in my other mail, I think the simplest
solution will be to restore the environment from a backup copy of the
original env. If we do that, this method won't be needed.
I have prototyped some of my suggestions to make sure they made sense.
I thought I would push them somewhere, feel free to use whatever you
want if that's useful to you:
https://github.com/simark/binutils-gdb/commits/remote-env
Thanks,
Simon
next prev parent reply other threads:[~2017-07-29 22:36 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-29 19:41 [PATCH] Implement the ability to transmit " Sergio Durigan Junior
2017-07-10 21:32 ` Sergio Durigan Junior
2017-07-13 21:47 ` Simon Marchi
2017-07-14 17:34 ` Sergio Durigan Junior
2017-07-27 3:36 ` [PATCH v2] Implement the ability to set/unset " Sergio Durigan Junior
2017-07-27 17:10 ` Eli Zaretskii
2017-07-27 22:05 ` Simon Marchi
2017-08-01 2:33 ` Sergio Durigan Junior
2017-08-01 9:35 ` Simon Marchi
2017-08-04 22:56 ` Sergio Durigan Junior
2017-07-29 22:36 ` Simon Marchi [this message]
2017-08-01 2:43 ` Sergio Durigan Junior
2017-08-01 9:54 ` Simon Marchi
2017-08-04 23:03 ` Sergio Durigan Junior
2017-08-05 18:14 ` Simon Marchi
2017-08-12 4:34 ` Sergio Durigan Junior
2017-08-12 8:11 ` Simon Marchi
[not found] ` <256083325d9f9c4cc4f5518fe6e5292d@polymtl.ca>
2017-08-12 4:19 ` Sergio Durigan Junior
2017-08-13 6:19 ` [PATCH v3] " Sergio Durigan Junior
2017-08-21 19:11 ` Sergio Durigan Junior
2017-08-24 19:25 ` Simon Marchi
2017-08-28 21:25 ` Sergio Durigan Junior
2017-08-28 23:13 ` [PATCH v4] " Sergio Durigan Junior
2017-08-31 19:37 ` Simon Marchi
2017-08-31 20:34 ` Sergio Durigan Junior
2017-08-31 20:39 ` Simon Marchi
2017-08-31 20:49 ` [PATCH v5] " Sergio Durigan Junior
2017-08-31 21:03 ` Simon Marchi
2017-08-31 21:26 ` Sergio Durigan Junior
2017-09-05 15:33 ` Thomas Preudhomme
2017-09-05 16:26 ` Simon Marchi
2017-09-05 17:09 ` Thomas Preudhomme
2017-09-05 18:41 ` Simon Marchi
2017-09-06 8:36 ` Thomas Preudhomme
2017-09-01 6:19 ` Eli Zaretskii
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d9dae60ba5a7e1aca29f15fe865f4110@polymtl.ca \
--to=simon.marchi@polymtl.ca \
--cc=eliz@gnu.org \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
--cc=sergiodj@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox