Author: Maciej Fijalkowski <fij...@gmail.com> Branch: vmprof Changeset: r75358:d14d2b0ad1b6 Date: 2015-01-15 18:16 +0200 http://bitbucket.org/pypy/pypy/changeset/d14d2b0ad1b6/
Log: reimport vmprof.c and wrap errors diff --git a/pypy/module/_vmprof/interp_vmprof.py b/pypy/module/_vmprof/interp_vmprof.py --- a/pypy/module/_vmprof/interp_vmprof.py +++ b/pypy/module/_vmprof/interp_vmprof.py @@ -3,10 +3,10 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rtyper.annlowlevel import cast_instance_to_gcref, cast_base_ptr_to_instance from rpython.rlib.objectmodel import we_are_translated, CDefinedIntSymbolic -from rpython.rlib import jit +from rpython.rlib import jit, rgc, rposix from rpython.tool.pairtype import extendabletype from pypy.interpreter.baseobjspace import W_Root -from pypy.interpreter.error import OperationError, oefmt +from pypy.interpreter.error import OperationError, oefmt, wrap_oserror from pypy.interpreter.gateway import interp2app, unwrap_spec from pypy.interpreter.pyframe import PyFrame from pypy.interpreter.pycode import PyCode @@ -36,7 +36,8 @@ separate_module_sources=[""" void pypy_vmprof_init(void) { - vmprof_set_mainloop(pypy_execute_frame_trampoline, 0, pypy_vmprof_get_virtual_ip); + vmprof_set_mainloop(pypy_execute_frame_trampoline, 0, + pypy_vmprof_get_virtual_ip); } """], ) @@ -59,14 +60,18 @@ _nowrapper=True, sandboxsafe=True, random_effects_on_gcobjs=True) -pypy_vmprof_init = rffi.llexternal("pypy_vmprof_init", [], lltype.Void, compilation_info=eci) -vmprof_enable = rffi.llexternal("vmprof_enable", [rffi.CCHARP, rffi.LONG], lltype.Void, compilation_info=eci) -vmprof_disable = rffi.llexternal("vmprof_disable", [], lltype.Void, compilation_info=eci) +pypy_vmprof_init = rffi.llexternal("pypy_vmprof_init", [], lltype.Void, + compilation_info=eci) +vmprof_enable = rffi.llexternal("vmprof_enable", + [rffi.INT, rffi.INT, rffi.LONG], + rffi.INT, compilation_info=eci) +vmprof_disable = rffi.llexternal("vmprof_disable", [], rffi.INT, + compilation_info=eci) -vmprof_register_virtual_function = rffi.llexternal("vmprof_register_virtual_function", - [rffi.CCHARP, rffi.VOIDP, rffi.VOIDP], - lltype.Void, - compilation_info=eci) +vmprof_register_virtual_function = rffi.llexternal( + "vmprof_register_virtual_function", + [rffi.CCHARP, rffi.VOIDP, rffi.VOIDP], lltype.Void, + compilation_info=eci) original_execute_frame = PyFrame.execute_frame.im_func original_execute_frame.c_name = 'pypy_pyframe_execute_frame' @@ -115,29 +120,57 @@ get_virtual_ip.c_name = 'pypy_vmprof_get_virtual_ip' get_virtual_ip._dont_inline_ = True +def strncpy(src, tgt, tgt_ofs, count): + if len(src) < count: + count = len(src) + i = 0 + while i < count: + tgt[i + tgt_ofs] = src[i] + i += 1 + return i + +def int2str(num, s, ofs): + if num == 0: + s[ofs] = '0' + return 1 + count = 0 + c = num + while c != 0: + count += 1 + c /= 10 + pos = ofs + count - 1 + c = num + while c != 0: + s[pos] = chr(ord('0') + c % 10) + c /= 10 + pos -= 1 + return count + +@rgc.no_collect def do_get_virtual_ip(frame): virtual_ip = frame.pycode._vmprof_virtual_ip - if frame.pycode._vmprof_registered != _vmprof.counter: + if not frame.pycode._vmprof_registered: # we need to register this code object name = frame.pycode.co_name + filename = frame.pycode.co_filename + firstlineno = frame.pycode.co_firstlineno start = rffi.cast(rffi.VOIDP, virtual_ip) end = start # ignored for now # # manually fill the C buffer; we cannot use str2charp because we # cannot call malloc from a signal handler strbuf = _vmprof.strbuf - strbuf[0] = 'p' - strbuf[1] = 'y' - strbuf[2] = ':' - maxbuflen = min(len(name), 124) - i = 0 - while i < maxbuflen: - strbuf[i+3] = name[i] - i += 1 - strbuf[i+3] = '\0' - # + ofs = strncpy("py:", _vmprof.strbuf, 0, len("py:")) + ofs += strncpy(filename, _vmprof.strbuf, ofs, 128) + _vmprof.strbuf[ofs] = ':' + ofs += 1 + ofs += int2str(firstlineno, _vmprof.strbuf, ofs) + _vmprof.strbuf[ofs] = ':' + ofs += 1 + ofs += strncpy(name, _vmprof.strbuf, ofs, 1024 - 1 - ofs) + _vmprof.strbuf[ofs] = '\x00' vmprof_register_virtual_function(strbuf, start, end) - frame.pycode._vmprof_registered = _vmprof.counter + frame.pycode._vmprof_registered = 1 # return virtual_ip @@ -146,9 +179,9 @@ class VMProf(object): def __init__(self): self.virtual_ip = 0 - self.counter = 0 # the number of times we called enable() self.is_enabled = False - self.strbuf = lltype.malloc(rffi.CCHARP.TO, 128, flavor='raw', immortal=True, zero=True) + self.ever_enabled = False + self.strbuf = lltype.malloc(rffi.CCHARP.TO, 1024, flavor='raw', immortal=True, zero=True) def get_next_virtual_IP(self): self.virtual_ip -= 1 @@ -158,23 +191,30 @@ def _annotate_get_virtual_ip(self): if FALSE_BUT_NON_CONSTANT: # make sure it's annotated - gcref = rffi.cast(llmemory.GCREF, self.counter) # just a random non-constant value + gcref = rffi.cast(llmemory.GCREF, self.virtual_ip) # just a random non-constant value get_virtual_ip(gcref) - def enable(self, space, filename, period): + def enable(self, space, fileno, symno, period): self._annotate_get_virtual_ip() if self.is_enabled: raise oefmt(space.w_ValueError, "_vmprof already enabled") self.is_enabled = True - pypy_vmprof_init() - self.counter += 1 - vmprof_enable(filename, period) + if not self.ever_enabled: + pypy_vmprof_init() + self.ever_enabled = True + res = vmprof_enable(fileno, symno, period) + if res == -1: + raise wrap_oserror(space, OSError(rposix.get_errno(), + "_vmprof.enable")) def disable(self, space): if not self.is_enabled: raise oefmt(space.w_ValueError, "_vmprof not enabled") - vmprof_disable() self.is_enabled = False + res = vmprof_disable() + if res == -1: + raise wrap_oserror(space, OSError(rposix.get_errno(), + "_vmprof.disable")) _vmprof = VMProf() diff --git a/pypy/module/_vmprof/src/vmprof.c b/pypy/module/_vmprof/src/vmprof.c --- a/pypy/module/_vmprof/src/vmprof.c +++ b/pypy/module/_vmprof/src/vmprof.c @@ -79,7 +79,6 @@ #include "get_custom_offset.c" - typedef struct { void* _unused1; void* _unused2; @@ -107,7 +106,7 @@ void* bp = (void*)sp + sp_offset; cp2->sp = bp; cp2->ip = ((void**)(bp - sizeof(void*))[0]; - // the ret is on the top of the stack + // the ret is on the top of the stack minus WORD return 1; } } @@ -198,16 +197,27 @@ * ************************************************************* */ -static void open_profile(const char* filename, long period_usec) { - char buf[4096]; - profile_file = fopen(filename, "wb"); +static int open_profile(int fd, int sym_fd, long period_usec) { + if ((fd = dup(fd)) == -1) { + return -1; + } + if ((sym_fd = dup(sym_fd)) == -1) { + return -1; + } + profile_file = fdopen(fd, "wb"); + if (!profile_file) { + return -1; + } prof_header(profile_file, period_usec); - assert(strlen(filename) < 4096); - sprintf(buf, "%s.sym", filename); - symbol_file = fopen(buf, "w"); + symbol_file = fdopen(sym_fd, "w"); + if (!symbol_file) { + return -1; + } + return 0; } -static void close_profile(void) { +static int close_profile(void) { + // XXX all of this can happily fail FILE* src; char buf[BUFSIZ]; size_t size; @@ -222,40 +232,50 @@ fclose(src); fclose(profile_file); fclose(symbol_file); + return 0; } -static void install_sigprof_handler(void) { +static int install_sigprof_handler(void) { struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_sigaction = sigprof_handler; sa.sa_flags = SA_RESTART | SA_SIGINFO; - sigemptyset(&sa.sa_mask); - sigaction(SIGPROF, &sa, NULL); + if (sigemptyset(&sa.sa_mask) == -1 || + sigaction(SIGPROF, &sa, NULL) == -1) { + return -1; + } + return 0; } -static void remove_sigprof_handler(void) { - signal(SIGPROF, SIG_DFL); +static int remove_sigprof_handler(void) { + //sighandler_t res = signal(SIGPROF, SIG_DFL); + //if (res == SIG_ERR) { + // return -1; + //} + return 0; }; -static void install_sigprof_timer(long period_usec) { +static int install_sigprof_timer(long period_usec) { static struct itimerval timer; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = period_usec; timer.it_value = timer.it_interval; if (setitimer(ITIMER_PROF, &timer, NULL) != 0) { - printf("Timer could not be initialized \n"); + return -1; } + return 0; } -static void remove_sigprof_timer(void) { +static int remove_sigprof_timer(void) { static struct itimerval timer; timer.it_interval.tv_sec = 0; timer.it_interval.tv_usec = 0; timer.it_value = timer.it_interval; if (setitimer(ITIMER_PROF, &timer, NULL) != 0) { - printf("Timer could not be deleted \n"); + return -1; } + return 0; } /* ************************************************************* @@ -270,18 +290,32 @@ mainloop_get_virtual_ip = get_virtual_ip; } -void vmprof_enable(const char* filename, long period_usec) { +int vmprof_enable(int fd, int sym_fd, long period_usec) { if (period_usec == -1) period_usec = 1000000 / 100; /* 100hz */ - open_profile(filename, period_usec); - install_sigprof_handler(); - install_sigprof_timer(period_usec); + if (open_profile(fd, sym_fd, period_usec) == -1) { + return -1; + } + if (install_sigprof_handler() == -1) { + return -1; + } + if (install_sigprof_timer(period_usec) == -1) { + return -1; + } + return 0; } -void vmprof_disable(void) { - remove_sigprof_timer(); - remove_sigprof_handler(); - close_profile(); +int vmprof_disable(void) { + if (remove_sigprof_timer() == -1) { + return -1; + } + if (remove_sigprof_handler() == -1) { + return -1; + } + if (close_profile() == -1) { + return -1; + } + return 0; } void vmprof_register_virtual_function(const char* name, void* start, void* end) { diff --git a/pypy/module/_vmprof/src/vmprof.h b/pypy/module/_vmprof/src/vmprof.h --- a/pypy/module/_vmprof/src/vmprof.h +++ b/pypy/module/_vmprof/src/vmprof.h @@ -12,7 +12,7 @@ void vmprof_register_virtual_function(const char* name, void* start, void* end); -void vmprof_enable(const char* filename, long period_usec); -void vmprof_disable(void); +int vmprof_enable(int fd, int sym_fd, long period_usec); +int vmprof_disable(void); #endif diff --git a/pypy/module/_vmprof/test/test__vmprof.py b/pypy/module/_vmprof/test/test__vmprof.py --- a/pypy/module/_vmprof/test/test__vmprof.py +++ b/pypy/module/_vmprof/test/test__vmprof.py @@ -13,6 +13,8 @@ def __init__(self, co_name): self.co_name = co_name + self.co_filename = 'filename' + self.co_firstlineno = 13 self._vmprof_setup_maybe() def test_get_virtual_ip(monkeypatch): @@ -31,7 +33,7 @@ _vmprof.counter = 42 ip = do_get_virtual_ip(myframe) assert ip == mycode._vmprof_virtual_ip - assert functions == [('py:foo', ip, ip)] + assert functions == [('py:filename:13:foo', ip, ip)] # the second time, we don't register it again functions = [] @@ -40,7 +42,7 @@ assert functions == [] # now, let's try with a long name - mycode = FakePyCode('abcde' * 200) + mycode = FakePyCode('abcde' + 'f' * 20000) myframe = FakePyFrame(mycode) functions = [] ip2 = do_get_virtual_ip(myframe) @@ -48,6 +50,6 @@ assert ip2 < ip # because it was generated later assert len(functions) == 1 name, start, end = functions[0] - assert len(name) == 127 - assert name == 'py:' + ('abcde'*200)[:124] + assert len(name) < 1025 + assert name == 'py:filename:13:abcde' + 'f' * (1024 - 20 - 1) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit