def main(argv): parser = OptionParser() parser.add_option('-v', '--verbose', action='store_true', dest='verbose', \ help='increase verbosity') parser.add_option('--pid', type='int', help='process id') parser.add_option('--pname', help='process name') parser.add_option('--log-file', dest='logfile', default='pyumdh.log', \ help='log file (default is %default)') opts, args = parser.parse_args(argv) binpath = utils.module_path() # load configuration and map its contents to a dict so that we could later # merge stock options with any dynamic content configpath = os.path.join(binpath, 'config.py') if os.path.exists(configpath): extconfig = imp.load_source('config', configpath) configopts = utils.Attributify(extconfig) else: configopts = utils.Attributify(config) log = logging.getLogger('umdh') log.addHandler(logging.StreamHandler()) if opts.logfile: log.addHandler(logging.FileHandler(opts.logfile)) if opts.verbose: log.setLevel(logging.DEBUG) datadir = utils.data_dir(configopts.get('WORK_DIR', binpath)) log.debug('data files are here=%s' % datadir) configerrors = [] if not configopts['DBG_BIN_PATHS']: log.warning('You might want to provide path to your application ' \ 'binaries for symbol lookup to work best\n(configure ' \ 'DBG_BIN_PATHS)') if not configopts['DBG_SYMBOL_PATHS']: log.warning('You might want to configure symbol paths for UMDH ' \ 'in DBG_SYMBOL_PATHS') if not configopts['DBG_TOOLS_PATH']: configerrors.append('You have to provide path to debugging tools for ' \ 'windows in DBG_TOOLS_PATH') if configerrors: error = '\n'.join(configerrors) log.critical(error) print 'If it is your first time running, please take time ' \ 'to go over config.py' return 1 # check if any .cache files are available # cache files are a handy way to continue working on a particular active # umdh session cachefiles = [fn for fn in os.listdir(datadir) if fnmatch(fn, '.cache.py')] if not cachefiles and not opts.pid and not opts.pname: print 'Specify either process name or process id' parser.print_help() return 2 if opts.pid or opts.pname: # if only process name has been specified, look up its pid pid = opts.pid or _find_pid(opts.pname, configopts) elif cachefiles: # currently, it makes sense to only handle a single cache file # i.e. file for the current session fn = cachefiles.pop() cachedconfig = imp.load_source('config', os.path.join(datadir, fn)) cachedopts = utils.Attributify(cachedconfig) configopts.update(cachedopts) pid = int(configopts['active_pid']) umdh(pid, configopts) return 0
_USAGE = """ Syntax: differ[.py] [options] [datafile1] [datafile2] --data-file options are optional, data files can be specified w/o qualification. More over, you can specify data files by their indices: differ 0 1 --out-file data\\0_1.log Will match data\\[pid]_snapshot_0.log and data\\[pid]_snapshot_1.log in the `data' working directory if pid can be read from the cached configuration (data\.cache.py). """ if __name__ == '__main__': freeze_support() binpath = utils.module_path() # load configuration and map its contents to a dict so that we could later # merge stock options with any dynamic content configpath = os.path.join(binpath, 'config.py') if os.path.exists(configpath): extconfig = imp.load_source('config', configpath) config = utils.Attributify(extconfig) else: config = utils.Attributify(config) parser = OptionParser() parser.add_option('--data-file', dest='logs', action='append', \ default=[], \ help='specify memory logs to diff; at (least and most) two are ' \ 'required') parser.add_option('--out-file', dest='outfile', \
self._path = [] super(WindowsLibraryLoader, self).__init__(*args, **kwargs) def add_path(self, fpath): self._path.append(fpath) def __getattr__(self, name): if name[0] == '_': raise AttributeError(name) dll = self._dlltype(name, self._path) setattr(self, name, dll) return dll wdll = WindowsLibraryLoader(WindowsLibrary) wdll.add_path(os.path.join(utils.module_path(), 'x64' if _win64() else 'x86')) from logging import getLogger class WinDll(WinDLL): """ Implements a windows library type that wraps all calls to provide error logging and throws WinError if a wrapped function call fails. Default error checking assumes that the wrapped api call returns zero in case of errors. This behaviour can be overriden by providing a callable to check for error condition: api_fn.errfn = lambda ret, args: check(ret) This also provides the ability to bypass error checking by providing a function to check errors that always defaults to True
class WindowsLibraryLoader(LibraryLoader): def __init__(self, *args, **kwargs): self._path = [] super(WindowsLibraryLoader, self).__init__(*args, **kwargs) def add_path(self, fpath): self._path.append(fpath) def __getattr__(self, name): if name[0] == '_': raise AttributeError(name) dll = self._dlltype(name, self._path) setattr(self, name, dll) return dll wdll = WindowsLibraryLoader(WindowsLibrary) wdll.add_path(os.path.join(utils.module_path(), 'x64' if _win64() else 'x86')) from logging import getLogger class WinDll(WinDLL): """ Implements a windows library type that wraps all calls to provide error logging and throws WinError if a wrapped function call fails. Default error checking assumes that the wrapped api call returns zero in case of errors. This behaviour can be overriden by providing a callable to check for error condition: api_fn.errfn = lambda ret, args: check(ret) This also provides the ability to bypass error checking by providing a function to check errors that always defaults to True