library: correct <pids> support of true string vectors

When reference counts were added to some string fields
the 3 true string vector fields were not duplicated as
were those other fields. Instead they were supposed to
disallow a duplicate stack reference beyond the first.
However, the actual implementation gave NULL for every
true vector field whenever such items were duplicated.

More importantly, such true string vector fields never
considered references to the shared proc_t source root
which would have forced the conversion of such vectors
into a single string form via the '_CVT' library flag.

So this commit restores the intended outcome with true
string vectors. There's only 1 valid reference allowed
and duplicates and converted fields will yield a NULL.

Signed-off-by: Jim Warner <james.warner@comcast.net>
This commit is contained in:
Jim Warner 2015-10-25 00:00:00 -05:00 committed by Craig Small
parent 9db796f8cb
commit 2b0dd2d702

View File

@ -58,10 +58,9 @@ enum pids_item PROCPS_PIDS_physical_end = PROCPS_PIDS_noop + 2;
// these represent the proc_t fields whose storage cannot be managed
// optimally if they are ever referenced more than once in any stack
enum rel_ref {
ref_CGROUP, ref_CGROUP_V, ref_CMD, ref_CMDLINE,
ref_CMDLINE_V, ref_ENVIRON, ref_ENVIRON_V, ref_SD_MACH,
ref_SD_OUID, ref_SD_SEAT, ref_SD_SESS, ref_SD_SLICE,
ref_SD_UNIT, ref_SD_UUNIT, ref_SUPGIDS, ref_SUPGROUPS,
ref_CGROUP, ref_CMD, ref_CMDLINE, ref_ENVIRON, ref_SD_MACH,
ref_SD_OUID, ref_SD_SEAT, ref_SD_SESS, ref_SD_SLICE, ref_SD_UNIT,
ref_SD_UUNIT, ref_SUPGIDS, ref_SUPGROUPS,
MAXIMUM_ref
};
@ -105,13 +104,6 @@ struct procps_pidsinfo {
// ___ Results 'Set' Support ||||||||||||||||||||||||||||||||||||||||||||||||||
static char **dupstrvecs (char **pvec) {
/* maybe someday we'll actually duplicate these string vectors but,
for now, let's just gently tell the user 'thanks, but no thanks'
( remember, that user was already provided with one valid copy ) */
return NULL;
}
#define setNAME(e) set_results_ ## e
#define setDECL(e) static void setNAME(e) \
(struct procps_pidsinfo *I, struct pids_result *R, proc_t *P)
@ -133,9 +125,15 @@ static char **dupstrvecs (char **pvec) {
#define STV_set(e,x) setDECL(e) { \
if (I->ref_counts[ref_ ## e] > 1) R->result.str = strdup(*P-> x); \
else { R->result.str = *P-> x; P-> x = NULL; } }
// take ownership of true vectorized strings if possible, else return NULL
#define VEC_set(e,x) setDECL(e) { \
if (I->ref_counts[ref_ ## e] > 1) R->result.strv = dupstrvecs(P-> x); \
/*
take ownership of true vectorized strings if possible, else return NULL
[ if there's a source field ref_count, then those true string vectors ]
[ have already been converted into a single string so we return NULL. ]
[ otherwise, the first result struct now gets ownership of those true ]
[ string vectors and any duplicate structures will then receive NULL. ]
*/
#define VEC_set(e1,e2,x) setDECL(e1) { \
if (I->ref_counts[ref_ ## e2]) R->result.strv = NULL; \
else { R->result.strv = P-> x; P-> x = NULL; } }
REG_set(ADDR_END_CODE, ul_int, end_code)
@ -146,12 +144,12 @@ REG_set(ADDR_START_STACK, ul_int, start_stack)
REG_set(ALARM, sl_int, alarm)
setDECL(CGNAME) { char *name = strstr(*P->cgroup, ":name="); if (name && *(name+6)) name += 6; else name = *P->cgroup; R->result.str = strdup(name); }
STV_set(CGROUP, cgroup)
VEC_set(CGROUP_V, cgroup)
VEC_set(CGROUP_V, CGROUP, cgroup)
STR_set(CMD, cmd)
STV_set(CMDLINE, cmdline)
VEC_set(CMDLINE_V, cmdline)
VEC_set(CMDLINE_V, CMDLINE, cmdline)
STV_set(ENVIRON, environ)
VEC_set(ENVIRON_V, environ)
VEC_set(ENVIRON_V, ENVIRON, environ)
REG_set(EXIT_SIGNAL, s_int, exit_signal)
REG_set(FLAGS, ul_int, flags)
REG_set(FLT_MAJ, ul_int, maj_flt)
@ -398,12 +396,12 @@ static struct {
{ RS(ALARM), f_stat, NULL, QS(sl_int), 0, -1 },
{ RS(CGNAME), x_cgroup, FF(str), QS(str), 0, ref_CGROUP }, // refcount: diff result, same source
{ RS(CGROUP), x_cgroup, FF(str), QS(str), 0, ref_CGROUP }, // refcount: diff result, same source
{ RS(CGROUP_V), v_cgroup, FF(strv), QS(strv), 0, ref_CGROUP_V },
{ RS(CGROUP_V), v_cgroup, FF(strv), QS(strv), 0, -1 },
{ RS(CMD), f_either, FF(str), QS(str), 0, ref_CMD },
{ RS(CMDLINE), x_cmdline, FF(str), QS(str), 0, ref_CMDLINE },
{ RS(CMDLINE_V), v_arg, FF(strv), QS(strv), 0, ref_CMDLINE_V },
{ RS(CMDLINE_V), v_arg, FF(strv), QS(strv), 0, -1 },
{ RS(ENVIRON), x_environ, FF(str), QS(str), 0, ref_ENVIRON },
{ RS(ENVIRON_V), v_env, FF(strv), QS(strv), 0, ref_ENVIRON_V },
{ RS(ENVIRON_V), v_env, FF(strv), QS(strv), 0, -1 },
{ RS(EXIT_SIGNAL), f_stat, NULL, QS(s_int), 0, -1 },
{ RS(FLAGS), f_stat, NULL, QS(ul_int), 0, -1 },
{ RS(FLT_MAJ), f_stat, NULL, QS(ul_int), 0, -1 },