Hi guys,
----- Original Message -----
> On 18/01/16 20:28, Marko Myllynen wrote:
> >
> > Consider this example (from the BZ):
> >
> > try:
> > self.context.pmRegisterDerived("foo", "rat(disk.dev.read)")
> > except:
> > print self.context.pmDerivedErrStr()
> >
> > Here pmDerivedErrStr returns nothing. Is this expected or should
> > pmDerivedErrStr be improved to return always something understandable in
> > case of errors?
> >
>
> Looks like a Python wrapper issue ... libpcp and friends get it right it
> would appear.
>
> kenj@bozo:~/src/pcp/qa$ pminfo -c /tmp/eek foo
> [/tmp/eek:1] Error: pmRegisterDerived(foo, ...) syntax error
> rat(disk.dev.read)
> ^
> Error: foo: Unknown metric name
> kenj@bozo:~/src/pcp/qa$ cat /tmp/eek
> foo = rat(disk.dev.read)
>
OK I dug into this some more ... it's getting complicated, and the libpcp
interface is at least partially responsible. :)
Firstly, I simplified your example program Marko, and extended it to show
the derived metric error handling that the python API provides currently.
$ /tmp/bad.py
PMAPI exception as requested
bad.py: Generic error, already reported above ['@', '(disk.dev.read)']
So, when you crack open the pmErr exception there, the position information
returned from pmRegisterDerived is available as an exception parameter, as
indicated by the [ @, <string> ] list message above.
Real problem arises when we subsequently call pmDerivedErrStr() - this is
using thread-local-storage for the error message (in libpcp). However,
from trawling the internets, it seems python may be switching the threads
underneath us ...
https://docs.python.org/2/c-api/init.html
"In order to emulate concurrency of execution, the interpreter regularly
tries to switch threads"
... which would explain the "None" message Markos test program reports,
on calling self.context.pmDerivedErrStr(), if we are now running on some
other thread.
Bleurgh. One way to tackle this would be to push that low-level python
GIL lock management into a new chunk of C code in the python wrapper, and
extract the pmDerivedErrStr right after calling pmRegisterDerived, while
still holding the GIL lock.
Another way would be to add a libpcp interface allowing a buffer to be
passed to a new pmRegisterDerived variant, which could do away with the
thread-local storage use and just put the message into the callers buffer.
Or like the pmParseInterval(3), pmParseTimeWindow(3), pmParseUnitsStr(3)
model, where a buffer is mallocd on failure, and passed back via a final
parameter for the caller to free.
Thoughts? Preferences? Does the derived metrics code lend itself to one
of these approached over others, Ken? Thanks. From the python wrappers
point of view, a new pmRegisterDerived variant would be the cleanest,
along the lines:
int pmRegisterDerivedMetric(char *name, char *expr, char **errmsg);
cheers.
--
Nathan
bad.py
Description: Text Data
|