Re: rasdaemon and abrt cooperation
by Denys Vlasenko
On 06/05/2013 03:25 PM, Petr Holasek wrote:
> Hi Denys,
>
> I have some ideas about rasdaemon abrt hook
> and also following questions.
>
> Feel free to stop by or ping me, when you'll
> be in office, I'll be there till ~6PM today
> and afternoon tomorrow.
Currently we use Unix domain socket at
/var/run/abrt/abrt.socket
to support creation of problem data from crashing python
applications.
The socket accepts the following HTTP requests:
DELETE <problem_dir> HTTP/1.1
PUT / HTTP/1.1
DELETE request is straightforward, and anyway, you don't need it.
PUT request has the following form:
PUT / HTTP/1.1<CR><LF>
headers<CR><LF>
<CR><LF>
name1=value1<NUL>name2=value2<NUL>...
It appears that we misunderstood HTTP protocol and we should
have used POST instead of PUT. I am going to add POST alias
which works the same as PUT, and remove PUT sometime in the future.
For now, use PUT. The URI in PUT should be just /.
The headers following PUT line are currently ignored.
The body is NUL-delimited (not newline delimited!) set
of name-value pairs which describe the problem.
You can use any names which make sense for your problem
(for example, if someone is reporting an out-of-paper
problem with a printer, sending "printer_name=FOO" would make sense).
Some names *have* to be in the problem:
type=
reason=
"type" describes what kind of the problem it is. Say, "Python"
is used by python crashes. You need to invent your own identifier(s)
for the problems you want to report. Say, "mem_error" for ECC/cache
errors, "bus_error" for PCI errors?
This field is used to differentiate abrt's response to a problem.
We don't want ECC errors reported to Bugzilla, right? :)
"reason" is a short, one-line, human-readable description of the problem,
suitable, for example, for showing in the list of problems. Examples
we currently see or use:
"<module>:ZeroDivisionError: integer division or modulo by zero"
"Segmentation fault at address 0x7ff6bf09e010"
"Process %s was killed by signal %s"
time=<unixtime in seconds> will be added automatically unless you supply it.
I looked thru the list of names we use and many don't make sense for you
(say, "uid" makes no sense for ECC errors :), but the following ones
may be useful:
architecture=<uname.machine>
comment=<long, multi-line description of the problem (if "reason" isn't enough)>
kernel=<kernel version>
cmdline=<kernel cmdline>
As I said, if you have more data to report, create your own name=value pair
to be saved.
Server will respond with
HTTP/1.1 <http_code> <CR><LF>
<CR><LF>
http_code will be 201 ("Created") on success.
Do you think you can use this interface from rasdaemon?
--
vda
10 years, 7 months
[PATCH 1/2] abrt-gdb-exploitable: x86 factoring-out
by Denys Vlasenko
No substantial logic changes.
Mostly renaming stuff and moving blocks of code around.
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
src/plugins/abrt-gdb-exploitable | 228 ++++++++++++++++++++-------------------
1 file changed, 117 insertions(+), 111 deletions(-)
diff --git a/src/plugins/abrt-gdb-exploitable b/src/plugins/abrt-gdb-exploitable
index e3d637b..f33ec45 100755
--- a/src/plugins/abrt-gdb-exploitable
+++ b/src/plugins/abrt-gdb-exploitable
@@ -30,11 +30,10 @@ def init_gettext():
gettext.bindtextdomain(GETTEXT_PROGNAME, '/usr/share/locale')
gettext.textdomain(GETTEXT_PROGNAME)
-
_WRITES_ALWAYS = -1
_WRITES_IF_MEMREF = -2
-_writing_instr = {
+_x86_writing_instr = {
# insn:N, where N:
# -1: this insn always writes to memory
# -2: writes to memory if any operand is a memory operand
@@ -198,7 +197,7 @@ _writing_instr = {
# Note: stack-writing instructions are omitted
}
-_pushing_instr = (
+_x86_pushing_instr = (
"push",
"pusha",
"pushf",
@@ -207,9 +206,9 @@ _pushing_instr = (
"lcall"
)
-_intdiv_instr = ("div", "idiv")
+_x86_intdiv_instr = ("div", "idiv")
-_jumping_instr = (
+_x86_jumping_instr = (
"jmp", # indirect jumps/calls with garbage data
"call", # call: also possible that stack is exhausted (infinite recursion)
"ljmp",
@@ -233,7 +232,10 @@ _jumping_instr = (
)
# stack was smashed if we crash on one of these
-_return_instr = ("iret", "lret", "ret")
+_x86_return_instr = ("iret", "lret", "ret")
+
+_x86_mem_op1_regex = re.compile("^((-?0x)|[(])")
+_x86_mem_op2_regex = re.compile("[,:]((-?0x)|[(])")
def _fetch_insn_from_table(ins, table):
if not ins:
@@ -251,50 +253,68 @@ def _fetch_insn_from_table(ins, table):
return ins
return None
+
class SignalAndInsn:
- def get_signal(self):
- self.signo = None
- try:
- # Requires new kernels which record complete siginfo
- # in coredumps (Linux 3.9 still don't have it),
- # and new gdb:
- sig = gdb.parse_and_eval("$_siginfo.si_signo")
- # Requires patched gdb:
- #sig = gdb.parse_and_eval("$_signo")
- #
- # type(sig) = <type 'gdb.Value'>, convert to plain int:
- self.signo = int(sig)
- except gdb.error:
- # "Python Exception <class 'gdb.error'>
- # Attempt to extract a component of a value that is not a structure"
- # Possible reasons why $_siginfo doesn't exist:
- # program is still running, program exited normally,
- # we work with a coredump from an old kernel.
- #
- # Lets see whether we are running from the abrt and it
- # provided us with signal number. Horrible hack :(
- #
- try:
- self.signo = int(os.environ["SIGNO_OF_THE_COREDUMP"])
- except KeyError:
+
+ def x86_instruction_is_store(self):
+ operand = _fetch_insn_from_table(self.mnemonic, _x86_writing_instr)
+ if not operand:
+ if not self.mnemonic:
return False
- return True
+ # There are far too many SSE store instructions,
+ # don't want to pollute the table with them.
+ # Special-case the check for MOVxxx
+ # and its SIMD cousins VMOVxxx:
+ if self.mnemonic[:3] != "mov" and self.mnemonic[:4] != "vmov":
+ return False
+ operand = 2
- def get_instruction(self):
- self.current_instruction = None
- self.mnemonic = None
- self.operands = ""
+ if operand == _WRITES_ALWAYS: # no need to check operands, it's a write
+ return True
+
+ # Memory operands look like this: [%seg:][[-]0xHEXNUM][(%reg[,...])]
+ # Careful with immediate operands which are $0xHEXNUM
+ # and FPU register references which are st(N).
+ if _x86_mem_op1_regex.search(self.operands):
+ mem_op_pos = 0
+ else:
+ match = _x86_mem_op2_regex.search(self.operands)
+ if not match:
+ return False # no memory operands
+ mem_op_pos = match.start() + 1
+
+ if operand == _WRITES_IF_MEMREF: # any mem operand indicates write
+ return True
+
+ comma = self.operands.find(",")
+ if mem_op_pos < comma:
+ # "%cs:0x0(%rax,%rax,1),foo" - 1st operand is memory
+ # "%cs:0x0(%rax),foo" - 1st operand is memory
+ memory_operand = 1
+ elif comma < 0:
+ # "%cs:0x0(%rax)" - 1st operand is memory
+ memory_operand = 1
+ else:
+ # mem_op_pos is after comma
+ # "foo,%cs:0x0(%rax,%rax,1)" - 2nd operand is memory
+ # (It also can be a third, fourth etc operand)
+ memory_operand = 2
+
+ if operand == memory_operand:
+ return True
+ return False
+
+ def x86_get_instruction(self):
try:
# just "disassemble $pc" won't work if $pc doesn't point
# inside a known function
- instructions = gdb.execute("disassemble $pc,$pc+32", to_string=True)
+ raw_instructions = gdb.execute("disassemble $pc,$pc+32", to_string=True)
except gdb.error:
# For example, if tracee already exited normally.
# Another observed case is if $pc points to unmapped area.
# We get "Python Exception <class 'gdb.error'> No registers"
return
- raw_instructions = instructions
instructions = []
current = None
for line in raw_instructions.split("\n"):
@@ -316,7 +336,7 @@ class SignalAndInsn:
if line:
instructions.append(line)
if current == None:
- # not False! we determined that $pc points to a bad address,
+ # we determined that $pc points to a bad address,
# which is an interesting fact.
return
@@ -344,76 +364,62 @@ class SignalAndInsn:
self.operands = t[1]
break
- mem_op1_regex = re.compile("^((-?0x)|[(])")
- mem_op2_regex = re.compile("[,:]((-?0x)|[(])")
+ self.instruction_is_pushing = (None != _fetch_insn_from_table(self.mnemonic, _x86_pushing_instr))
+ self.instruction_is_division = (None != _fetch_insn_from_table(self.mnemonic, _x86_intdiv_instr))
+ self.instruction_is_branch = (None != _fetch_insn_from_table(self.mnemonic, _x86_jumping_instr))
+ self.instruction_is_return = (None != _fetch_insn_from_table(self.mnemonic, _x86_return_instr))
+ self.instruction_is_store = self.x86_instruction_is_store()
- def instruction_is_writing(self):
- operand = _fetch_insn_from_table(self.mnemonic, _writing_instr)
- if not operand:
- if not self.mnemonic:
- return False
- # There are far too many SSE store instructions,
- # don't want to pollute the table with them.
- # Special-case the check for MOVxxx
- # and its SIMD cousins VMOVxxx:
- if self.mnemonic[:3] != "mov" and self.mnemonic[:4] != "vmov":
- return False
- operand = 2
- if operand == _WRITES_ALWAYS: # no need to check operands, it's a write
- return True
-
- # Memory operands look like this: [%seg:][[-]0xHEXNUM][(%reg[,...])]
- # Careful with immediate operands which are $0xHEXNUM
- # and FPU register references which are st(N).
- if SignalAndInsn.mem_op1_regex.search(self.operands):
- mem_op_pos = 0
- else:
- match = SignalAndInsn.mem_op2_regex.search(self.operands)
- if not match:
- return False # no memory operands
- mem_op_pos = match.start() + 1
-
- if operand == _WRITES_IF_MEMREF: # any mem operand indicates write
- return True
-
- comma = self.operands.find(",")
- if mem_op_pos < comma:
- # "%cs:0x0(%rax,%rax,1),foo" - 1st operand is memory
- # "%cs:0x0(%rax),foo" - 1st operand is memory
- memory_operand = 1
- elif comma < 0:
- # "%cs:0x0(%rax)" - 1st operand is memory
- memory_operand = 1
- else:
- # mem_op_pos is after comma
- # "foo,%cs:0x0(%rax,%rax,1)" - 2nd operand is memory
- # (It also can be a third, fourth etc operand)
- memory_operand = 2
-
- if operand == memory_operand:
- return True
- return False
-
- def instruction_is_pushing(self):
- if _fetch_insn_from_table(self.mnemonic, _pushing_instr):
- return True
- return False
-
- def instruction_is_division(self):
- if _fetch_insn_from_table(self.mnemonic, _intdiv_instr):
- return True
- return False
-
- def instruction_is_jumping(self):
- if _fetch_insn_from_table(self.mnemonic, _jumping_instr):
- return True
- return False
+ def get_instruction(self):
+ self.current_instruction = None
+ self.mnemonic = None
+ self.operands = ""
+ self.instruction_is_division = None
+ self.instruction_is_store = None
+ self.instruction_is_pushing = None
+ self.instruction_is_return = None
+ self.instruction_is_branch = None
+ try:
+ arch = gdb.execute("show architecture", to_string=True)
+ # Examples of the string we get:
+ # The target architecture is set automatically (currently i386)
+ # The target architecture is set automatically (currently i386:x86-64)
+ # The target architecture is set automatically (currently powerpc:common64)
+ if " i386" in arch:
+ return self.x86_get_instruction()
+ #if " powerpc" in arch:
+ # return self.ppc_get_instruction()
+ except gdb.error:
+ return
- def instruction_is_return(self):
- if _fetch_insn_from_table(self.mnemonic, _return_instr):
- return True
- return False
+ def get_signal(self):
+ self.signo = None
+ try:
+ # Requires new kernels which record complete siginfo
+ # in coredumps (Linux 3.9 still don't have it),
+ # and new gdb:
+ sig = gdb.parse_and_eval("$_siginfo.si_signo")
+ # Requires patched gdb:
+ #sig = gdb.parse_and_eval("$_signo")
+ #
+ # type(sig) = <type 'gdb.Value'>, convert to plain int:
+ self.signo = int(sig)
+ except gdb.error:
+ # "Python Exception <class 'gdb.error'>
+ # Attempt to extract a component of a value that is not a structure"
+ # Possible reasons why $_siginfo doesn't exist:
+ # program is still running, program exited normally,
+ # we work with a coredump from an old kernel.
+ #
+ # Lets see whether we are running from the abrt and it
+ # provided us with signal number. Horrible hack :(
+ #
+ try:
+ self.signo = int(os.environ["SIGNO_OF_THE_COREDUMP"])
+ except KeyError:
+ return False
+ return True
#Our initial set of testing will use the list Apple included in their
#CrashWrangler announcement:
@@ -467,7 +473,7 @@ class SignalAndInsn:
elif self.signo == signal.SIGFPE:
self.exploitable_rating = 1
self.exploitable_desc = _("Arithmetic exception")
- if self.instruction_is_division():
+ if self.instruction_is_division:
self.exploitable_rating = 0
self.exploitable_desc = _("Division by zero")
elif self.signo == signal.SIGILL:
@@ -476,18 +482,18 @@ class SignalAndInsn:
# TODO: check that sig is SIGSEGV/SIGBUS?
- elif self.instruction_is_pushing():
+ elif self.instruction_is_pushing:
self.exploitable_rating = 4
self.exploitable_desc = _("Stack overflow")
- elif self.instruction_is_writing():
+ elif self.instruction_is_store:
self.exploitable_rating = 6
self.exploitable_desc = _("Write to an invalid address")
- elif self.instruction_is_return():
+ elif self.instruction_is_return:
self.exploitable_rating = 7
self.exploitable_desc = _("Subroutine return to an invalid address (corrupted stack?)")
# Note: we check "ret" first, _then_ jumps.
# Corrupted stack is different from corrupted data.
- elif self.instruction_is_jumping():
+ elif self.instruction_is_branch:
self.exploitable_rating = 6
self.exploitable_desc = _("Jump to an invalid address")
elif not self.current_instruction:
--
1.8.1.4
10 years, 10 months
[GNOME-ABRT PATCH] Display two sets of problems (My/System)
by Jakub Filak
Closes rhbz#973125
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gnome-abrt | 24 ++-
src/gnome_abrt/controller.py.in | 18 +-
src/gnome_abrt/dbus_problems.py | 207 ++++++++++++++-----
src/gnome_abrt/errors.py | 4 +-
src/gnome_abrt/oops.glade | 79 ++++++--
src/gnome_abrt/problems.py | 80 +++++---
src/gnome_abrt/views.py | 428 ++++++++++++++++++++++++++++------------
7 files changed, 595 insertions(+), 245 deletions(-)
diff --git a/src/gnome-abrt b/src/gnome-abrt
index 65db955..b9be029 100755
--- a/src/gnome-abrt
+++ b/src/gnome-abrt
@@ -22,6 +22,7 @@ import os
import sys
import logging
import signal
+import traceback
from argparse import ArgumentParser
# pygobject
@@ -40,7 +41,8 @@ from gnome_abrt.controller import Controller
from gnome_abrt.signals import glib_sigchld_signal_handler
from gnome_abrt.problems import MultipleSources
from gnome_abrt.directory_problems import DirectoryProblemSource
-from gnome_abrt.dbus_problems import DBusProblemSource
+from gnome_abrt.dbus_problems import (get_standard_problems_source,
+ get_foreign_problems_source)
from gnome_abrt.errors import UnavailableSource
from gnome_abrt.l10n import _
from gnome_abrt.wrappers import show_events_list_dialog
@@ -157,7 +159,7 @@ class OopsApplication(Gtk.Application):
self.connect("command-line", self._parse_command_line)
self.set_flags(Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
self.gcontext = None
- self.source = None
+ self.all_sources = None
self._url_pool = GetURLTitleSourcePool(GNOME_ABRT_URL_POOL_CAPACITY)
self._url_cache = GetURLTitleSourceCache(self._url_pool)
gnome_abrt.url.set_async_worker(self._url_cache.get_url_title_async)
@@ -188,26 +190,28 @@ class OopsApplication(Gtk.Application):
sources = []
try:
- sources.append(DBusProblemSource(self._dbus_srv.mainloop))
- except UnavailableSource as ex:
- logging.warning(ex)
+ sources.append(
+ get_standard_problems_source(self._dbus_srv.mainloop))
+ except UnavailableSource:
+ logging.warning(traceback.format_exc())
self.gcontext = GLib.main_context_default()
try:
path = os.path.join(GLib.get_user_cache_dir(), "abrt/spool")
dps = DirectoryProblemSource(path, context=self.gcontext)
sources.append(dps)
- except UnavailableSource as ex:
- logging.warning(ex)
+ except UnavailableSource:
+ logging.warning(traceback.format_exc())
if len(sources) == 0:
raise UnavailableSource("No available problem source.")
- self.source = MultipleSources(sources)
+ self.all_sources = [(_("My"), MultipleSources(sources)),
+ (_("System"), get_foreign_problems_source())]
- controller = Controller(self.source,
+ controller = Controller(self.all_sources,
glib_sigchld_signal_handler)
- main_window = OopsWindow(self, self.source, controller)
+ main_window = OopsWindow(self, self.all_sources, controller)
main_window.show_all()
self.add_window (main_window)
#pylint: disable=W0703
diff --git a/src/gnome_abrt/controller.py.in b/src/gnome_abrt/controller.py.in
index f48e26d..0dad426 100644
--- a/src/gnome_abrt/controller.py.in
+++ b/src/gnome_abrt/controller.py.in
@@ -18,11 +18,15 @@
import logging
import os
import sys
+import traceback
+
+# gnome-abrt
+from gnome_abrt import errors
class Controller(object):
- def __init__(self, source, sigchld_assign=None):
- self.source = source
+ def __init__(self, sources, sigchld_assign=None):
+ self.sources = sources
self.run_event_fn = self._first_event_run
self._sigchld_assign = sigchld_assign
@@ -47,9 +51,17 @@ class Controller(object):
self.run_event_fn("open-gui", problem)
+ def _refresh_sources(self):
+ for name, src in self.sources:
+ try:
+ src.refresh()
+ except errors.UnavailableSource:
+ logging.debug("Cannot refresh problem source {0}: {1}"
+ .format(name, traceback.format_exc()))
+
def _first_event_run(self, event, problem):
if self._sigchld_assign is not None:
- self._sigchld_assign(self.source.refresh)
+ self._sigchld_assign(self._refresh_sources)
self.run_event_fn = self._run_event_on_problem
self.run_event_fn(event, problem)
diff --git a/src/gnome_abrt/dbus_problems.py b/src/gnome_abrt/dbus_problems.py
index c035606..1c964d5 100644
--- a/src/gnome_abrt/dbus_problems.py
+++ b/src/gnome_abrt/dbus_problems.py
@@ -17,6 +17,7 @@
import os
import dbus
+import traceback
from dbus.mainloop.glib import DBusGMainLoop
import logging
@@ -33,9 +34,42 @@ BUS_IFACE = 'org.freedesktop.problems'
ABRTD_DBUS_PATH = '/org/freedesktop/problems'
ABRTD_DBUS_SIGNAL = 'Crash'
+def get_standard_problems_source(mainloop=None):
+ return DBusProblemSource(StandardProblems, mainloop)
+
+def get_foreign_problems_source(mainloop=None):
+ return DBusProblemSource(ForeignProblems, mainloop)
+
class DBusProblemSource(problems.CachedSource):
- def __init__(self, mainloop=None):
+ class Driver(object):
+ """Handles differences in behaviour while working with different sets
+ of problems obtained from D-Bus service.
+ """
+
+ def __init__(self, source):
+ self._source = source
+
+ @property
+ def get_problems_method(self):
+ """Gets an instance of a method used for obtaining problems from
+ D-Bus service.
+ """
+
+ raise NotImplementedError()
+
+ def on_new_problem(self, *args):
+ """Process a notification about detected problem."""
+
+ raise NotImplementedError()
+
+ def on_dbus_exception(self, problem_id, ex):
+ """Process D-Bus errors."""
+
+ raise NotImplementedError()
+
+
+ def __init__(self, driverclass, mainloop=None):
super(DBusProblemSource, self).__init__()
self._mainloop = mainloop
@@ -55,17 +89,7 @@ class DBusProblemSource(problems.CachedSource):
_("Can't add receiver of signal '{0}'on DBus system path '{1}': {2}")
.format(ABRTD_DBUS_SIGNAL, ABRTD_DBUS_PATH, ex))
- class ConfigObserver():
- def __init__(self, source):
- self.source = source
-
- #pylint: disable=W0613
- def option_updated(self, conf, option):
- if option == "all_problems":
- self.source.refresh()
-
- conf = config.get_configuration()
- conf.set_watch("all_problems", ConfigObserver(self))
+ self._driver = driverclass(self)
def _connect_to_problems_bus(self):
# I can't find any description of raised exceptions
@@ -74,14 +98,14 @@ class DBusProblemSource(problems.CachedSource):
try:
self._proxy = self._bus.get_object(BUS_NAME, BUS_PATH)
except dbus.exceptions.DBusException as ex:
- raise errors.UnavailableSource(
+ raise errors.UnavailableSource(self, False,
_("Can't connect to DBus system bus '{0}' path '{1}': {2}")
.format(BUS_NAME, BUS_PATH, ex))
try:
self._interface = dbus.Interface(self._proxy, BUS_IFACE)
except dbus.exceptions.DBusException as ex:
- raise errors.UnavailableSource(
+ raise errors.UnavailableSource(self, False,
_("Can't get interface '{0}' on path '{1}' in bus '{2}': {3}")
.format(BUS_IFACE, BUS_PATH, BUS_NAME, ex))
@@ -111,21 +135,9 @@ class DBusProblemSource(problems.CachedSource):
.format(args))
return
- conf = config.get_configuration()
- if (len(args) > 2
- and int(args[2]) != os.getuid()
- and not conf['all_problems']):
- logging.debug("Received the new problem signal with different uid "
- "'{0}' ('{1}') and the all problems option is not configured"
- .format(args[2], os.getuid()))
- return
-
- if len(args) == 2 and not conf['all_problems']:
- logging.debug("Received the new problem signal without the uid "
- "argument and the all problems option is not configured")
- return
-
- self.process_new_problem_id(str(args[1]))
+ prblm_id = self._driver.on_new_problem(*args)
+ if prblm_id is not None:
+ self.process_new_problem_id(prblm_id)
def chown_problem(self, problem_id):
try:
@@ -150,12 +162,7 @@ class DBusProblemSource(problems.CachedSource):
lambda iface, *params: iface.GetInfo(*params),
problem_id, args)
except dbus.exceptions.DBusException as ex:
- if ex.get_dbus_name() in [
- "org.freedesktop.problems.AuthFailure",
- "org.freedesktop.problems.InvalidProblemDir"]:
- self._remove_from_cache(problem_id)
- raise errors.InvalidProblem(problem_id, ex)
-
+ self._driver.on_dbus_exception(problem_id, ex)
logging.warning(
_("Can't get problem data from DBus service: {0!s}")
.format(ex))
@@ -163,19 +170,9 @@ class DBusProblemSource(problems.CachedSource):
return info
def _get_problems(self):
- conf = config.get_configuration()
-
prblms = []
-
try:
- if conf['all_problems']:
- prblms = self._send_dbus_message(
- #pylint: disable=W0142
- lambda iface, *args: iface.GetAllProblems(*args))
- else:
- prblms = self._send_dbus_message(
- #pylint: disable=W0142
- lambda iface, *args: self._interface.GetProblems(*args))
+ prblms = self._send_dbus_message(self._driver.get_problems_method)
except dbus.exceptions.DBusException as ex:
logging.warning(
_("Can't get list of problems from DBus service: {0!s}")
@@ -190,12 +187,120 @@ class DBusProblemSource(problems.CachedSource):
lambda iface, *args: iface.DeleteProblem(*args), [problem_id])
return True
except dbus.exceptions.DBusException as ex:
- if ex.get_dbus_name() in ["org.freedesktop.problems.AuthFailure",
- "org.freedesktop.problems.InvalidProblemDir"]:
- self._remove_from_cache(problem_id)
- raise errors.InvalidProblem(problem_id, ex)
-
+ self._driver.on_dbus_exception(problem_id, ex)
logging.warning(
_("Can't delete problem over DBus service: {0!s}")
.format(ex))
return False
+
+
+class StandardProblems(DBusProblemSource.Driver):
+ """The old behaviour."""
+
+ def __init__(self, source):
+ super(StandardProblems, self).__init__(source)
+
+ class ConfigObserver():
+ def __init__(self, source):
+ self._source = source
+
+ #pylint: disable=W0613
+ def option_updated(self, conf, option):
+ if option == "all_problems":
+ self._source.refresh()
+
+ conf = config.get_configuration()
+ conf.set_watch("all_problems", ConfigObserver(self._source))
+
+ @property
+ def get_problems_method(self):
+ conf = config.get_configuration()
+ if conf['all_problems']:
+ #pylint: disable=W0142
+ return lambda iface, *args: iface.GetAllProblems(*args)
+ else:
+ #pylint: disable=W0142
+ return lambda iface, *args: iface.GetProblems(*args)
+
+ def on_new_problem(self, *args):
+ """Accepts foreign problems only if the all_problems option is enabled
+ """
+
+ conf = config.get_configuration()
+ try:
+ if (len(args) > 2
+ and int(args[2]) != os.getuid()
+ and not conf['all_problems']):
+ logging.debug("Received the new problem signal with different "
+ "uid '{0}' ('{1}') and the all problems option "
+ "is not configured" .format(args[2], os.getuid()))
+ return None
+ except ValueError:
+ logging.debug(traceback.format_exc())
+ return None
+
+ if len(args) == 2 and not conf['all_problems']:
+ logging.debug("Received the new problem signal without the uid "
+ "argument and the all problems option is not configured")
+ return None
+
+ return str(args[1])
+
+ def on_dbus_exception(self, problem_id, ex):
+ """Process AuthFailure error in same way as InvalidProblemDir because
+ this sort of problem source provides all kinds of problems. The user
+ problems which should be always accessible and the foreign problems
+ which may be inaccessible when a user cancels the authentication
+ dialogue. So, an AuthFailure error in this context means that a one
+ of many problems is unavailable (something like an invalid problem).
+ """
+
+ if ex.get_dbus_name() in ["org.freedesktop.problems.AuthFailure",
+ "org.freedesktop.problems.InvalidProblemDir"]:
+ self._source._remove_from_cache(problem_id)
+ raise errors.InvalidProblem(problem_id, ex)
+
+
+class ForeignProblems(DBusProblemSource.Driver):
+
+ def __init__(self, source):
+ super(ForeignProblems, self).__init__(source)
+
+ @property
+ def get_problems_method(self):
+ #pylint: disable=W0142
+ return lambda iface, *args: iface.GetForeignProblems(*args)
+
+ def on_new_problem(self, *args):
+ """Accepts only foreign problems."""
+
+ args_len = len(args)
+ try:
+ if args_len == 2 or (args_len > 2 and int(args[2]) != os.getuid()):
+ return str(args[1])
+ except ValueError:
+ logging.debug(traceback.format_exc())
+ return None
+
+ logging.debug("Received the new problem signal with current user's uid "
+ "'{0}' ('{1}') in ForeignPorblems driver"
+ .format(args[2], os.getuid()))
+
+ return None
+
+ def on_dbus_exception(self, problem_id, ex):
+ """If the authentication fails, a foreign problems source become
+ temporary unavailable because we expect that the failure was caused by
+ dismissing of the authentication dialog and all problems provided by
+ this kind of source require authentication (none of them is available
+ now). So, it means that a view can try to query the temporary
+ unavailable source later.
+ """
+
+ if ex.get_dbus_name() == "org.freedesktop.problems.AuthFailure":
+ logging.debug("User dismissed D-Bus authentication")
+ raise errors.UnavailableSource(self._source, True)
+
+ if ex.get_dbus_name() == "org.freedesktop.problems.InvalidProblemDir":
+ self._source._remove_from_cache(problem_id)
+ raise errors.InvalidProblem(problem_id, ex)
diff --git a/src/gnome_abrt/errors.py b/src/gnome_abrt/errors.py
index fffaf5e..777b85e 100644
--- a/src/gnome_abrt/errors.py
+++ b/src/gnome_abrt/errors.py
@@ -29,5 +29,7 @@ class InvalidProblem(GnomeAbrtError):
class UnavailableSource(GnomeAbrtError):
- def __init__(self, message=None):
+ def __init__(self, source, temporary, message=None):
super(UnavailableSource, self).__init__(message)
+ self.source = source
+ self.temporary = temporary
diff --git a/src/gnome_abrt/oops.glade b/src/gnome_abrt/oops.glade
index b9b4b1a..497c386 100644
--- a/src/gnome_abrt/oops.glade
+++ b/src/gnome_abrt/oops.glade
@@ -433,9 +433,6 @@
</packing>
</child>
<child>
- <placeholder/>
- </child>
- <child>
<object class="GtkLabel" id="lbl_reported">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -469,6 +466,12 @@
<property name="height">1</property>
</packing>
</child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
<property name="left_attach">1</property>
@@ -560,6 +563,39 @@
<property name="tab_fill">False</property>
</packing>
</child>
+ <child>
+ <object class="GtkBox" id="vbx_no_source_page">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="orientation">vertical</property>
+ <child>
+ <object class="GtkLabel" id="lbl_no_source">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">No source selected!</property>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ </packing>
+ </child>
+ <child type="tab">
+ <object class="GtkLabel" id="lbl_page_no_source">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="label" translatable="yes">No source</property>
+ </object>
+ <packing>
+ <property name="position">2</property>
+ <property name="tab_fill">False</property>
+ </packing>
+ </child>
</object>
<packing>
<property name="left_attach">1</property>
@@ -575,6 +611,26 @@
<property name="margin_top">10</property>
<property name="orientation">vertical</property>
<child>
+ <object class="GtkBox" id="hbox_source_btns">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="fill">True</property>
+ <property name="position">0</property>
+ </packing>
+ </child>
+ <child>
<object class="GtkScrolledWindow" id="sw_problems">
<property name="visible">True</property>
<property name="can_focus">True</property>
@@ -630,23 +686,6 @@
<packing>
<property name="expand">True</property>
<property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="chb_all_problems">
- <property name="related_action">gac_opt_all_problems</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="margin_top">10</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="pack_type">end</property>
<property name="position">1</property>
</packing>
</child>
diff --git a/src/gnome_abrt/problems.py b/src/gnome_abrt/problems.py
index 314dfcf..96a34ee 100644
--- a/src/gnome_abrt/problems.py
+++ b/src/gnome_abrt/problems.py
@@ -22,8 +22,7 @@ import logging
import gnome_abrt.url
from gnome_abrt.application import find_application
from gnome_abrt.errors import (InvalidProblem,
- UnavailableSource,
- GnomeAbrtError)
+ UnavailableSource)
from gnome_abrt.l10n import _
class ProblemSource(object):
@@ -112,7 +111,7 @@ class Problem:
self.source = source
self.app = None
self.submission = None
- self.data = self._get_initial_data(self.source)
+ self.data = None
self._deleted = False
def __str__(self):
@@ -142,6 +141,9 @@ class Problem:
return items
def __getitem__(self, item, cached=True):
+ if self.data is None:
+ self.data = self._get_initial_data(self.source)
+
if item == 'date':
return datetime.datetime.fromtimestamp(float(self['time']))
if item == 'date_last':
@@ -197,17 +199,8 @@ class Problem:
self.source.notify(ProblemSource.CHANGED_PROBLEM, self)
def delete(self):
- # TODO : weird?? the assignemt can be moved
+ self.source.delete_problem(self.problem_id)
self._deleted = True
- try:
- self.source.delete_problem(self.problem_id)
- except GnomeAbrtError as ex:
- logging.warning(_("Can't delete problem '{0}': '{1}'")
- .format(self.problem_id, ex))
- self._deleted = False
- except Exception as ex:
- self._deleted = False
- raise
def is_reported(self):
return not self['reported_to'] is None
@@ -297,13 +290,34 @@ class MultipleSources(ProblemSource):
self._disable_notify = False
+ def __eq__(self, other):
+ if other is None:
+ return False
+
+ return (super(MultipleSources, self) == other
+ or other in self.sources)
+
+ def _pop_source(self, index):
+ self.sources.pop(index)
+ if not self.sources:
+ raise UnavailableSource()
+
def get_items(self, problem_id, *args):
pass
def get_problems(self):
result = []
- for src in self.sources:
- result.extend(src.get_problems())
+ i = 0
+ while i != len(self.sources):
+ try:
+ result.extend(self.sources[i].get_problems())
+ i += 1
+ except UnavailableSource as ex:
+ logging.debug("{0}".format(str(ex)))
+ if not ex.temporary:
+ self._pop_source(i)
+ else:
+ i += 1
return result
@@ -323,8 +337,17 @@ class MultipleSources(ProblemSource):
self._disable_notify = True
try:
- for src in self.sources:
- src.refresh()
+ i = 0
+ while i != len(self.sources):
+ try:
+ self.sources[i].refresh()
+ i += 1
+ except UnavailableSource as ex:
+ logging.debug("{0}".format(str(ex)))
+ if not ex.temporary:
+ self._pop_source(i)
+ else:
+ i += 1
finally:
self._disable_notify = False
@@ -345,9 +368,7 @@ class CachedSource(ProblemSource):
try:
self._cache.append(self._create_new_problem(prblmid))
except InvalidProblem as ex:
- logging.warning(ex)
- except UnavailableSource as ex:
- logging.warning(ex)
+ logging.warning(str(ex))
return self._cache if self._cache else []
@@ -390,19 +411,14 @@ class CachedSource(ProblemSource):
self._cache = None
self.notify()
-
def _create_new_problem(self, problem_id):
return Problem(problem_id, self)
def process_new_problem_id(self, problem_id):
- try:
- if self._problem_is_in_cache(problem_id):
- prblm = self._cache[self._cache.index(problem_id)]
- prblm.refresh()
- else:
- prblm = self._create_new_problem(problem_id)
- self._insert_to_cache(prblm)
- self.notify(ProblemSource.NEW_PROBLEM, prblm)
- except UnavailableSource as ex:
- logging.warning(_("Source failed on processing of '{0}': {1}")
- .format(problem_id, ex))
+ if self._problem_is_in_cache(problem_id):
+ prblm = self._cache[self._cache.index(problem_id)]
+ prblm.refresh()
+ else:
+ prblm = self._create_new_problem(problem_id)
+ self._insert_to_cache(prblm)
+ self.notify(ProblemSource.NEW_PROBLEM, prblm)
diff --git a/src/gnome_abrt/views.py b/src/gnome_abrt/views.py
index ebc8908..6fa512b 100644
--- a/src/gnome_abrt/views.py
+++ b/src/gnome_abrt/views.py
@@ -22,6 +22,7 @@ import time
import logging
import subprocess
import locale
+import traceback
#pygobject
#pylint: disable=E0611
@@ -97,6 +98,27 @@ def time_sort_func(model, first, second, view):
logging.debug(ex)
return 0
+def format_button_source_name(name, source):
+ return "{0} ({1})".format(name, len(source.get_problems()))
+
+def handle_problem_and_source_errors(func):
+ """Wraps repetitive exception handling."""
+
+ def wrapper_for_instance_function(oops_wnd, *args):
+ try:
+ return func(oops_wnd, *args)
+ except errors.InvalidProblem as ex:
+ logging.debug(traceback.format_exc())
+ oops_wnd._remove_problem_from_storage(ex.problem_id)
+ except errors.UnavailableSource as ex:
+ logging.debug(traceback.format_exc())
+ oops_wnd._disable_source(ex.source, ex.temporary)
+
+ return None
+
+ return wrapper_for_instance_function
+
+
#pylint: disable=R0902
class OopsWindow(Gtk.ApplicationWindow):
class OopsGtkBuilder(object):
@@ -154,11 +176,54 @@ class OopsWindow(Gtk.ApplicationWindow):
return obj
- def __init__(self, application, source, controller):
+ class SourceObserver:
+ def __init__(self, wnd):
+ self.wnd = wnd
+ self._enabled = True
+
+ def enable(self):
+ self._enabled = True
+
+ def disable(self):
+ self._enabled = False
+
+ def changed(self, source, change_type=None, problem=None):
+ if not self._enabled:
+ return
+
+ try:
+ if source == self.wnd._source:
+ if not change_type:
+ self.wnd._reload_problems(source)
+ elif change_type == problems.ProblemSource.NEW_PROBLEM:
+ self.wnd._add_problem_to_storage(problem)
+ elif change_type == problems.ProblemSource.DELETED_PROBLEM:
+ self.wnd._remove_problem_from_storage(problem)
+ elif change_type == problems.ProblemSource.CHANGED_PROBLEM:
+ self.wnd._update_problem_in_storage(problem)
+
+ self.wnd._update_source_button(source)
+ except errors.UnavailableSource as ex:
+ self.wnd._disable_source(ex.source, ex.temporary)
+
+
+ class OptionsObserver:
+ def __init__(self, wnd):
+ self.wnd = wnd
+
+ def option_updated(self, conf, option):
+ if option == 'problemid' and conf[option]:
+ self.wnd._select_problem_by_id(conf[option])
+
+
+ def __init__(self, application, sources, controller):
Gtk.ApplicationWindow.__init__(self,
title=_('Automatic Bug Reporting Tool'),
application=application)
+ if not sources:
+ raise ValueError("The source list cannot be empty!")
+
self._builder = OopsWindow.OopsGtkBuilder()
self.set_default_size(*self._builder.wnd_main.get_size())
self._builder.wnd_main.remove(self._builder.gr_main_layout)
@@ -176,60 +241,150 @@ class OopsWindow(Gtk.ApplicationWindow):
stl_ctx.add_provider_for_screen(stl_ctx.get_screen(), css_prv, 6000)
self._builder.connect_signals(self)
- self.selected_problem = None
- self._source = source
+ self._source_observer = OopsWindow.SourceObserver(self)
+ self._source_observer.disable()
+
self._reloading = False
self._controller = controller
+ self.selected_problem = None
+ self._all_sources = []
+ self._source = None
+ self._handling_source_click = False
+ for name, src in sources:
+ self._all_sources.append(src)
+ src.attach(self._source_observer)
+
+ label = None
+ try:
+ label = format_button_source_name(name, src)
+ except errors.UnavailableSource:
+ logging.debug("Unavailable source: {0}".format(name))
+ continue
+
+ src_btn = Gtk.ToggleButton(label)
+ src_btn.set_visible(True)
+ # add an extra member source (I don't like it but it so easy)
+ src_btn.source = src
+ self._builder.hbox_source_btns.pack_start(src_btn,
+ True, True, 0)
+
+ # add an extra member name (I don't like it but it so easy)
+ src.name = name
+ # add an extra member button (I don't like it but it so easy)
+ src.button = src_btn
+ src_btn.connect("clicked", self._on_source_btn_clicked, src)
+
+ self._source = self._all_sources[0]
+ self._set_button_toggled(self._source.button, True)
+
self._builder.ls_problems.set_sort_column_id(0, Gtk.SortType.DESCENDING)
self._builder.ls_problems.set_sort_func(0, time_sort_func, self)
self._filter = ProblemsFilter(self, self._builder.tv_problems)
- class SourceObserver:
- def __init__(self, wnd):
- self.wnd = wnd
-
- def changed(self, source, change_type=None, problem=None):
- if not change_type:
- self.wnd._reload_problems(source)
- elif change_type == problems.ProblemSource.NEW_PROBLEM:
- self.wnd._add_problem_to_storage(problem)
- elif change_type == problems.ProblemSource.DELETED_PROBLEM:
- self.wnd._remove_problem_from_storage(problem)
- elif change_type == problems.ProblemSource.CHANGED_PROBLEM:
- self.wnd._update_problem_in_storage(problem)
-
-
- self._source_observer = SourceObserver(self)
- self._source.attach(self._source_observer)
-
self._builder.tv_problems.grab_focus()
- self._reload_problems(self._source)
-
- class OptionsObserver:
- def __init__(self, wnd):
- self.wnd = wnd
-
- def option_updated(self, conf, option):
- if option == 'problemid' and conf[option]:
- self.wnd._select_problem_by_id(conf[option])
+ try:
+ self._reload_problems(self._source)
+ except errors.UnavailableSource as ex:
+ self._disable_source(ex.source, ex.temporary)
- self._options_observer = OptionsObserver(self)
+ self._options_observer = OopsWindow.OptionsObserver(self)
conf = config.get_configuration()
conf.set_watch('problemid', self._options_observer)
self._options_observer.option_updated(conf, 'problemid')
self._builder.btn_detail.set_visible(conf['expert'])
self._builder.mi_detail.set_visible(conf['expert'])
+ # enable observer
+ self._source_observer.enable()
+
+ def _update_source_button(self, source):
+ name = format_button_source_name(source.name, source)
+ source.button.set_label(name)
+
+ def _set_button_toggled(self, button, state):
+ # set_active() triggers the clicked signal
+ # and if we set the active in program,
+ # we don't want do any action in the clicked handler
+ self._handling_source_click = True
+ try:
+ button.set_active(state)
+ finally:
+ self._handling_source_click = False
+
+ def _on_source_btn_clicked(self, btn, args):
+ # If True, then button's state was not changed by click
+ # and we don't want to switch source
+ if self._handling_source_click:
+ return
+
+ res, old_source = self._switch_source(btn.source)
+ if not res:
+ self._set_button_toggled(btn, False)
+ elif old_source is not None:
+ self._set_button_toggled(old_source.button, False)
+
+ def _switch_source(self, source):
+ """Sets the passed source as the selected source."""
+
+ result = True
+ old_source = None
+ if source != self._source:
+ try:
+ self._reload_problems(source)
+ old_source = self._source
+ self._source = source
+ except errors.UnavailableSource as ex:
+ self._disable_source(source, ex.temporary)
+ result = False
+
+ return (result, old_source)
+
+ def _disable_source(self, source, temporary):
+ if self._source is None or not self._all_sources:
+ return
+
+ # Some sources can be components of other sources.
+ # Problems are connected directly to the component sources, therefore
+ # exception's source is a component source, thus we have to find an
+ # instance of composite source which the unavailable component source
+ # belongs.
+ source_index = self._all_sources.index(source)
+
+ if source_index != -1:
+ real_source = self._all_sources[source_index]
+ self._set_button_toggled(real_source.button, False)
+ if not temporary:
+ logging.debug("Disabling source")
+ real_source.button.set_sensitive(False)
+ self._all_sources.pop(source_index)
+
+ if source != self._source:
+ return
+
+ # We just disabled the currently selected source. So, we should select
+ # some other source. The simplest way is to select the first source
+ # but only if it is not the disabled source.
+ # If the disabled source is completely unavailable (not temporary) we
+ # can always select the source at index 0 because the disabled
+ # source was removed from the _all_sources list.
+ if (not temporary or source_index != 0) and self._all_sources:
+ self._source = self._all_sources[0]
+ self._set_button_toggled(self._source.button, True)
+ else:
+ self._source = None
+
+ try:
+ self._reload_problems(self._source)
+ except errors.UnavailableSource as ex:
+ self._disable_source(ex.source, ex.temporary)
+
+ @handle_problem_and_source_errors
def _find_problem_iter(self, problem, model):
pit = model.get_iter_first()
while pit:
- try:
- if model[pit][2] == problem:
- return pit
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ if model[pit][2] == problem:
+ return pit
pit = model.iter_next(pit)
@@ -245,8 +400,8 @@ class OopsWindow(Gtk.ApplicationWindow):
self._builder.ls_problems.append(problem_to_storage_values(problem))
return True
except errors.InvalidProblem as ex:
+ logging.debug("Exception: {0}".format(traceback.format_exc()))
self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
return False
def _remove_problem_from_storage(self, problem):
@@ -262,35 +417,46 @@ class OopsWindow(Gtk.ApplicationWindow):
if pit:
try:
values = problem_to_storage_values(problem)
- for i in xrange(0, len(values)-1):
- self._builder.ls_problems.set_value(pit, i, values[i])
except errors.InvalidProblem as ex:
+ logging.debug("Exception: {0}".format(traceback.format_exc()))
self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
return
- try:
- if problem in self._get_selected(self._builder.tvs_problems):
- self._set_problem(problem)
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ for i in xrange(0, len(values)-1):
+ self._builder.ls_problems.set_value(pit, i, values[i])
+
+ if problem in self._get_selected(self._builder.tvs_problems):
+ self._set_problem(problem)
def _reload_problems(self, source):
- self._reloading = True
+ # Try to load and prepare the list of selected problems before we
+ # clear the view. So, we can gracefully handle UnavailableSource
+ # exception. If the reloaded source is unavailable the old list
+ # of problems remains untouched.
+ storage_problems = []
+ if source is not None:
+ prblms = source.get_problems()
+ for p in prblms:
+ try:
+ storage_problems.append(problem_to_storage_values(p))
+ except errors.InvalidProblem:
+ logging.debug("Exception: {0}"
+ .format(traceback.format_exc()))
+
old_selection = self._get_selected(self._builder.tvs_problems)
- canselect = False
+
+ self._reloading = True
+ old_selection = None
try:
self._builder.ls_problems.clear()
- prblms = source.get_problems()
- # Can select a problem only if at least one problem was added to
- # the storage
- for p in prblms:
- canselect |= self._add_problem_to_storage(p)
+
+ if storage_problems:
+ for p in storage_problems:
+ self._builder.ls_problems.append(p)
finally:
self._reloading = False
- if canselect:
+ if storage_problems:
model = self._builder.tv_problems.get_model()
pit = None
if old_selection:
@@ -306,8 +472,22 @@ class OopsWindow(Gtk.ApplicationWindow):
self._set_problem(None)
def _select_problem_by_id(self, problem_id):
+ # The problem could come from a different source than the currently
+ # loaded source. If so, try to switch to problem's origin source and
+ # select the problem after that.
+ if (self._source is not None and
+ not problem_id in self._source.get_problems()):
+ for source in self._all_sources:
+ if problem_id in source.get_problems():
+ res, old_source = self._switch_source(source)
+ if res:
+ self._set_button_toggled(old_source.button, False)
+ self._set_button_toggled(source.button, True)
+ break
+
pit = self._find_problem_iter(problem_id,
self._builder.tv_problems.get_model())
+
if pit:
self._select_problem_iter(pit)
else:
@@ -358,58 +538,58 @@ class OopsWindow(Gtk.ApplicationWindow):
self._builder.vbx_problem_messages.pack_start(msg, False, True, 0)
+ @handle_problem_and_source_errors
def _set_problem(self, problem):
- try:
- self.selected_problem = problem
-
- sensitive_btn = problem is not None
- self._builder.btn_delete.set_sensitive(sensitive_btn)
- self._builder.btn_report.set_sensitive(
- sensitive_btn and not problem['not-reportable'] )
- self._builder.btn_detail.set_sensitive(sensitive_btn)
- self._builder.vbx_links.foreach(
- lambda w, u: w.destroy(), None)
- self._builder.vbx_problem_messages.foreach(
- lambda w, u: w.destroy(), None)
-
- if problem:
- self._builder.nb_problem_layout.set_current_page(0)
- app = problem['application']
- self._builder.lbl_summary.set_text(problem['reason'] or "")
- self._builder.lbl_app_name_value.set_text(app.name or _("N/A"))
- self._builder.lbl_reason.set_text("{0} {1}".format(
- app.name or _("N/A"), _(' crashed').strip()))
- self._builder.lbl_app_version_value.set_text(
- problem['package'] or "")
- self._builder.lbl_detected_value.set_text(
- problem['date'].strftime(
- locale.nl_langinfo(locale.D_FMT)))
-
- if app.icon:
- self._builder.img_app_icon.set_from_pixbuf(app.icon)
- else:
- self._builder.img_app_icon.clear()
-
- if problem['is_reported']:
- self._builder.lbl_reported_value.set_text(_('yes'))
- self._show_problem_links(problem['submission'])
- else:
- self._builder.lbl_reported_value.set_text(_('no'))
-
- if problem['not-reportable']:
- self._show_problem_message(problem['not-reportable'])
- elif (not problem['is_reported']
- or not any((s.name == "Bugzilla"
- for s in problem['submission']))):
- self._show_problem_message(
- _("This problem hasn't been reported to <i>Bugzilla</i> yet. "
- "Our developers may need more information to fix the problem.\n"
- "Please consider <b>reporting it</b> - you may help them. Thank you."))
+ self.selected_problem = problem
+
+ sensitive_btn = problem is not None
+ self._builder.btn_delete.set_sensitive(sensitive_btn)
+ self._builder.btn_report.set_sensitive(
+ sensitive_btn and not problem['not-reportable'] )
+ self._builder.btn_detail.set_sensitive(sensitive_btn)
+ self._builder.vbx_links.foreach(
+ lambda w, u: w.destroy(), None)
+ self._builder.vbx_problem_messages.foreach(
+ lambda w, u: w.destroy(), None)
+
+ if problem:
+ self._builder.nb_problem_layout.set_current_page(0)
+ app = problem['application']
+ self._builder.lbl_summary.set_text(problem['reason'] or "")
+ self._builder.lbl_app_name_value.set_text(app.name or _("N/A"))
+ self._builder.lbl_reason.set_text("{0} {1}".format(
+ app.name or _("N/A"), _(' crashed').strip()))
+ self._builder.lbl_app_version_value.set_text(
+ problem['package'] or "")
+ self._builder.lbl_detected_value.set_text(
+ problem['date'].strftime(
+ locale.nl_langinfo(locale.D_FMT)))
+
+ if app.icon:
+ self._builder.img_app_icon.set_from_pixbuf(app.icon)
+ else:
+ self._builder.img_app_icon.clear()
+
+ if problem['is_reported']:
+ self._builder.lbl_reported_value.set_text(_('yes'))
+ self._show_problem_links(problem['submission'])
else:
+ self._builder.lbl_reported_value.set_text(_('no'))
+
+ if problem['not-reportable']:
+ self._show_problem_message(problem['not-reportable'])
+ elif (not problem['is_reported']
+ or not any((s.name == "Bugzilla"
+ for s in problem['submission']))):
+ self._show_problem_message(
+_("This problem hasn't been reported to <i>Bugzilla</i> yet. "
+ "Our developers may need more information to fix the problem.\n"
+ "Please consider <b>reporting it</b> - you may help them. Thank you."))
+ else:
+ if self._source is not None:
self._builder.nb_problem_layout.set_current_page(1)
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ else:
+ self._builder.nb_problem_layout.set_current_page(2)
def _get_selected(self, selection):
model, rows = selection.get_selected_rows()
@@ -434,38 +614,30 @@ class OopsWindow(Gtk.ApplicationWindow):
# Clear window because of empty list of problems!
self._set_problem(None)
+ @handle_problem_and_source_errors
def on_gac_delete_activate(self, action):
- try:
- for prblm in self._get_selected(self._builder.tvs_problems):
+ for prblm in self._get_selected(self._builder.tvs_problems):
+ try:
self._controller.delete(prblm)
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ except errors.InvalidProblem as ex:
+ logging.debug(traceback.format_exc())
+ self._remove_problem_from_storage(ex.problem_id)
+ @handle_problem_and_source_errors
def on_gac_detail_activate(self, action):
- try:
- selected = self._get_selected(self._builder.tvs_problems)
- if selected:
- self._controller.detail(selected[0])
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ selected = self._get_selected(self._builder.tvs_problems)
+ if selected:
+ self._controller.detail(selected[0])
+ @handle_problem_and_source_errors
def on_gac_report_activate(self, action):
- try:
- selected = self._get_selected(self._builder.tvs_problems)
- if selected and not selected[0]['not-reportable']:
- self._controller.report(selected[0])
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ selected = self._get_selected(self._builder.tvs_problems)
+ if selected and not selected[0]['not-reportable']:
+ self._controller.report(selected[0])
+ @handle_problem_and_source_errors
def on_te_search_changed(self, entry):
- try:
- self._filter.set_pattern(entry.get_text())
- except errors.InvalidProblem as ex:
- self._remove_problem_from_storage(ex.problem_id)
- logging.debug(ex)
+ self._filter.set_pattern(entry.get_text())
def on_gac_opt_all_problems_activate(self, action):
conf = config.get_configuration()
--
1.8.2.1
10 years, 10 months
[SATYR PATCH 1/3] Fix paths in public headers
by Martin Milata
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
include/core/frame.h | 2 +-
include/core/stacktrace.h | 2 +-
include/core/thread.h | 2 +-
include/gdb/frame.h | 2 +-
include/gdb/stacktrace.h | 2 +-
include/gdb/thread.h | 2 +-
include/java/frame.h | 2 +-
include/java/stacktrace.h | 2 +-
include/java/thread.h | 2 +-
include/koops/frame.h | 2 +-
include/koops/stacktrace.h | 2 +-
include/python/frame.h | 2 +-
include/python/stacktrace.h | 2 +-
13 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/include/core/frame.h b/include/core/frame.h
index c7817db..cc6c462 100644
--- a/include/core/frame.h
+++ b/include/core/frame.h
@@ -29,7 +29,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <inttypes.h>
#include <stdbool.h>
diff --git a/include/core/stacktrace.h b/include/core/stacktrace.h
index 765bdec..2169ef7 100644
--- a/include/core/stacktrace.h
+++ b/include/core/stacktrace.h
@@ -29,7 +29,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <inttypes.h>
struct sr_core_thread;
diff --git a/include/core/thread.h b/include/core/thread.h
index 23bfd59..42617e5 100644
--- a/include/core/thread.h
+++ b/include/core/thread.h
@@ -29,7 +29,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <inttypes.h>
diff --git a/include/gdb/frame.h b/include/gdb/frame.h
index a9b71bd..06dfc0e 100644
--- a/include/gdb/frame.h
+++ b/include/gdb/frame.h
@@ -29,7 +29,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/include/gdb/stacktrace.h b/include/gdb/stacktrace.h
index f7eff36..ed63f82 100644
--- a/include/gdb/stacktrace.h
+++ b/include/gdb/stacktrace.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
struct sr_gdb_thread;
diff --git a/include/gdb/thread.h b/include/gdb/thread.h
index f601b8f..8970f65 100644
--- a/include/gdb/thread.h
+++ b/include/gdb/thread.h
@@ -29,7 +29,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/include/java/frame.h b/include/java/frame.h
index b1be1c9..57eb96e 100644
--- a/include/java/frame.h
+++ b/include/java/frame.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/include/java/stacktrace.h b/include/java/stacktrace.h
index ef16918..e58c08c 100644
--- a/include/java/stacktrace.h
+++ b/include/java/stacktrace.h
@@ -33,7 +33,7 @@ extern "C" {
struct sr_java_thread;
struct sr_location;
-#include "report_type.h"
+#include "../report_type.h"
#include <stdint.h>
struct sr_java_stacktrace
diff --git a/include/java/thread.h b/include/java/thread.h
index 0fd8c6e..cf10a6d 100644
--- a/include/java/thread.h
+++ b/include/java/thread.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/include/koops/frame.h b/include/koops/frame.h
index 269fb73..cc69904 100644
--- a/include/koops/frame.h
+++ b/include/koops/frame.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/include/koops/stacktrace.h b/include/koops/stacktrace.h
index 9d76cab..85bc755 100644
--- a/include/koops/stacktrace.h
+++ b/include/koops/stacktrace.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <inttypes.h>
#include <stddef.h>
diff --git a/include/python/frame.h b/include/python/frame.h
index a02a6b1..362b402 100644
--- a/include/python/frame.h
+++ b/include/python/frame.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdbool.h>
#include <stdint.h>
diff --git a/include/python/stacktrace.h b/include/python/stacktrace.h
index 22c9f02..6223dc1 100644
--- a/include/python/stacktrace.h
+++ b/include/python/stacktrace.h
@@ -30,7 +30,7 @@
extern "C" {
#endif
-#include "report_type.h"
+#include "../report_type.h"
#include <stdint.h>
struct sr_python_frame;
--
1.7.11.7
10 years, 10 months
[SATYR PATCH 0/3] Implement bthashes
by Martin Milata
Related to https://github.com/abrt/satyr/issues/66, duphash implementation will
follow.
Martin Milata (3):
Higher-level function for SHA1 hashes in hex encoding
Implement bthashes
python: bindings for bthash
include/stacktrace.h | 22 ++++++++++++++++++
lib/core_fingerprint.c | 10 +-------
lib/core_frame.c | 23 +++++++++++++++++++
lib/core_stacktrace.c | 15 ++++++++++++
lib/core_thread.c | 3 +++
lib/gdb_frame.c | 24 +++++++++++++++++++
lib/gdb_stacktrace.c | 21 +++++++++++++++++
lib/gdb_thread.c | 14 ++++++++++++
lib/generic_frame.c | 9 ++++++++
lib/generic_frame.h | 9 ++++++++
lib/generic_stacktrace.c | 43 ++++++++++++++++++++++++++++++++++
lib/generic_stacktrace.h | 4 ++++
lib/generic_thread.c | 16 +++++++++++++
lib/generic_thread.h | 14 ++++++++++++
lib/internal_utils.h | 3 +++
lib/java_frame.c | 22 ++++++++++++++++++
lib/java_stacktrace.c | 9 ++++++++
lib/java_thread.c | 13 +++++++++++
lib/koops_frame.c | 27 ++++++++++++++++++++++
lib/koops_stacktrace.c | 34 +++++++++++++++++++++++++++
lib/python_frame.c | 21 +++++++++++++++++
lib/python_stacktrace.c | 16 +++++++++++++
lib/sha1.c | 16 +++++++++++++
lib/sha1.h | 5 ++++
python/py_base_stacktrace.c | 56 +++++++++++++++++++++++++++++++++++++++++++++
python/py_base_stacktrace.h | 2 ++
python/py_module.c | 4 ++++
tests/python/gdb.py | 3 +++
tests/python/java.py | 2 ++
tests/python/koops.py | 3 +++
tests/python/python.py | 3 +++
31 files changed, 457 insertions(+), 9 deletions(-)
--
1.7.11.7
10 years, 10 months
[ABRT PATCH 1/2] problem API: add function getting list of inaccessible problem IDs
by Jakub Filak
Related to rhbz#973125
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/include/problem_api.h | 31 ++++++++++++++++++++++++++++++-
src/lib/problem_api.c | 31 ++++++++++++++++++++++++++++++-
2 files changed, 60 insertions(+), 2 deletions(-)
diff --git a/src/include/problem_api.h b/src/include/problem_api.h
index 99d832c..60a76d0 100644
--- a/src/include/problem_api.h
+++ b/src/include/problem_api.h
@@ -20,9 +20,29 @@
#include <glib.h>
#include <libabrt.h>
+
+/*
+ * Function called for each problem directory in @for_each_problem_in_dir
+ *
+ * @param dd A dump directory
+ * @param arg User's arguments
+ * @returns 0 if everything is OK, a non zero value in order to break the iterator
+ */
+typedef int (* for_each_problem_in_dir_callback)(struct dump_dir *dd, void *arg);
+
+/*
+ * Iterates over all dump directories placed in @path and call @callback.
+ *
+ * @param path Dump directories location
+ * @param caller_uid UID for access check. -1 for disabling this check
+ * @param callback Called for each applicable dump directory. Non zero
+ * value returned from @callback will breaks the iteration.
+ * @param arg User's arguments passed to @callback
+ * @returns 0 or the first non zero value returned from @callback
+ */
int for_each_problem_in_dir(const char *path,
uid_t caller_uid,
- int (*callback)(struct dump_dir *dd, void *arg),
+ for_each_problem_in_dir_callback callback,
void *arg);
/* Retrieves the list of directories currently used as a problem storage
@@ -31,3 +51,12 @@ int for_each_problem_in_dir(const char *path,
*/
GList *get_problem_storages(void);
GList *get_problem_dirs_for_uid(uid_t uid, const char *dump_location);
+
+/*
+ * Gets list of problem directories not accessible by user
+ *
+ * @param uid User's uid
+ * @param dump_location Dump directories location
+ * @returns GList with mallocated absolute paths to dump directories
+ */
+GList *get_problem_dirs_not_accessible_by_uid(uid_t uid, const char *dump_location);
diff --git a/src/lib/problem_api.c b/src/lib/problem_api.c
index 3bb114f..7523efb 100644
--- a/src/lib/problem_api.c
+++ b/src/lib/problem_api.c
@@ -46,7 +46,7 @@ int for_each_problem_in_dir(const char *path,
continue; /* skip "." and ".." */
char *full_name = concat_path_file(path, dent->d_name);
- if (dump_dir_accessible_by_uid(full_name, caller_uid))
+ if (caller_uid == -1 || dump_dir_accessible_by_uid(full_name, caller_uid))
{
/* Silently ignore *any* errors, not only EACCES.
* We saw "lock file is locked by process PID" error
@@ -91,6 +91,35 @@ GList *get_problem_dirs_for_uid(uid_t uid, const char *dump_location)
return g_list_reverse(list);
}
+/* get_problem_dirs_not_accessible_by_uid and its helpers */
+struct add_dirname_to_GList_if_not_accessible_args
+{
+ uid_t uid;
+ GList *list;
+};
+
+static int add_dirname_to_GList_if_not_accessible(struct dump_dir *dd, void *args)
+{
+ struct add_dirname_to_GList_if_not_accessible_args *param = (struct add_dirname_to_GList_if_not_accessible_args *)args;
+ /* Append if not accessible */
+ if (!dump_dir_accessible_by_uid(dd->dd_dirname, param->uid))
+ param->list = g_list_prepend(param->list, xstrdup(dd->dd_dirname));
+
+ return 0;
+}
+
+GList *get_problem_dirs_not_accessible_by_uid(uid_t uid, const char *dump_location)
+{
+ struct add_dirname_to_GList_if_not_accessible_args args = {
+ .uid = uid,
+ .list = NULL,
+ };
+
+ for_each_problem_in_dir(dump_location, /*disable default uid check*/-1, add_dirname_to_GList_if_not_accessible, &args);
+ return g_list_reverse(args.list);
+}
+
+
/* get_problem_storages */
GList *get_problem_storages(void)
--
1.8.2.1
10 years, 10 months
[ABRT PATCH] the system tray icon opens recently detected problem
by Jakub Filak
Related to rhbz#973125
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/applet/applet.c | 33 +++++++++++++++++++++------------
1 file changed, 21 insertions(+), 12 deletions(-)
diff --git a/src/applet/applet.c b/src/applet/applet.c
index 4773d06..568237a 100644
--- a/src/applet/applet.c
+++ b/src/applet/applet.c
@@ -63,12 +63,13 @@ enum
static GDBusConnection *g_system_bus;
static GtkStatusIcon *ap_status_icon;
static GtkWidget *ap_menu;
-static char *ap_last_problem_dir;
static char **s_dirs;
static GList *g_deferred_crash_queue;
static guint g_deferred_timeout;
static int g_signal_pipe[2];
static ignored_problems_t *g_ignore_set;
+/* Used only for selection of the last notified problem if a user clicks on the systray icon */
+static char *g_last_notified_problem_id;
static bool is_autoreporting_enabled(void)
{
@@ -744,7 +745,7 @@ static GtkWidget *create_menu(void)
static void on_applet_activate_cb(GtkStatusIcon *status_icon, gpointer user_data)
{
- fork_exec_gui(/* problem id */ NULL);
+ fork_exec_gui(g_last_notified_problem_id);
hide_icon();
}
@@ -799,16 +800,21 @@ static void notify_problem_list(GList *problems, int flags)
/* show icon and don't try to show notify if initialization of libnotify failed */
flags |= SHOW_ICON_ONLY;
+ GList *last_item = g_list_last(problems);
+ if (last_item == NULL)
+ {
+ VERB3 log("Not showing any notification bubble because the list of problems is empty.");
+ return;
+ }
+
+ problem_info_t *last_problem = (problem_info_t *)last_item->data;
+ free(g_last_notified_problem_id);
+ g_last_notified_problem_id = xstrdup(last_problem->problem_dir);
+
if (!persistence_supported || flags & SHOW_ICON_ONLY)
{
/* Use a message of the last one */
- GList *last = g_list_last(problems);
-
- if (last)
- {
- problem_info_t *pi = (problem_info_t *)last->data;
- show_icon(pi->message);
- }
+ show_icon(last_problem->message);
}
if (flags & SHOW_ICON_ONLY)
@@ -1167,10 +1173,11 @@ static void Crash(DBusMessage* signal)
*/
static time_t last_time = 0;
static char* last_package_name = NULL;
+ static char *last_problem_dir = NULL;
time_t cur_time = time(NULL);
int flags = 0;
if (last_package_name && strcmp(last_package_name, package_name) == 0
- && ap_last_problem_dir && strcmp(ap_last_problem_dir, dir) == 0
+ && last_problem_dir && strcmp(last_problem_dir, dir) == 0
&& (unsigned)(cur_time - last_time) < 2 * 60 * 60
) {
/* log_msg doesn't show in .xsession_errors */
@@ -1182,8 +1189,8 @@ static void Crash(DBusMessage* signal)
last_time = cur_time;
free(last_package_name);
last_package_name = xstrdup(package_name);
- free(ap_last_problem_dir);
- ap_last_problem_dir = xstrdup(dir);
+ free(last_problem_dir);
+ last_problem_dir = xstrdup(dir);
}
problem_info_t *pi = problem_info_new();
@@ -1531,5 +1538,7 @@ next:
g_dbus_connection_signal_unsubscribe(g_system_bus, signal_ret);
g_object_unref(g_system_bus);
+ free(g_last_notified_problem_id);
+
return 0;
}
--
1.8.2.1
10 years, 10 months
[LIBREPORT PATCH] wizard: show accurate messages
by Jakub Filak
Closes rhbz#973167
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gui-wizard-gtk/wizard.c | 36 ++++++++++++------------------------
1 file changed, 12 insertions(+), 24 deletions(-)
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index 9c867ca..1c7d75d 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -113,7 +113,7 @@ static GtkWidget *g_top_most_window;
static void add_workflow_buttons(GtkBox *box, GHashTable *workflows, GCallback func);
static void set_auto_event_chain(GtkButton *button, gpointer user_data);
-static void setup_and_start_event_run(const char *event_name);
+static void start_event_run(const char *event_name);
typedef struct
{
@@ -1348,7 +1348,6 @@ struct analyze_event_data
struct run_event_state *run_state;
char *event_name;
GList *env_list;
- const char *success_msg;
GIOChannel *channel;
struct strbuf *event_log;
int event_log_state;
@@ -1677,7 +1676,7 @@ static void on_btn_failed_cb(GtkButton *button)
clear_warnings();
update_ls_details_checkboxes(EMERGENCY_ANALYSIS_EVENT_NAME);
- setup_and_start_event_run(EMERGENCY_ANALYSIS_EVENT_NAME);
+ start_event_run(EMERGENCY_ANALYSIS_EVENT_NAME);
/* single shot button -> hide after click */
gtk_widget_hide(GTK_WIDGET(button));
@@ -1802,11 +1801,6 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g
/* Hide spinner and stop btn */
gtk_widget_hide(GTK_WIDGET(g_spinner_event_log));
- if (retval != 0)
- gtk_widget_show(GTK_WIDGET(g_img_process_fail));
- else
- gtk_widget_show(GTK_WIDGET(g_img_process_ok));
-
gtk_widget_hide(g_btn_stop);
/* Enable (un-gray out) navigation buttons */
gtk_widget_set_sensitive(g_btn_close, true);
@@ -1817,9 +1811,10 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g
if (retval != 0)
{
+ gtk_widget_show(GTK_WIDGET(g_img_process_fail));
/* 256 means NOT_REPORTABLE */
if (retval == 256)
- cancel_processing(g_lbl_event_log, evd->success_msg);
+ cancel_processing(g_lbl_event_log, _("Processing was interrupted because the problem is not reportable."));
else
{
/* We use SIGTERM to stop event processing on user's request.
@@ -1835,7 +1830,11 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g
}
}
else
- gtk_label_set_text(g_lbl_event_log, evd->success_msg);
+ {
+ gtk_widget_show(GTK_WIDGET(g_img_process_ok));
+ gtk_label_set_text(g_lbl_event_log, is_processing_finished() ? _("Processing finished.")
+ : _("Processing finished, please proceed to the next step."));
+ }
/*g_source_remove(evd->event_source_id);*/
close(evd->fd);
@@ -1870,9 +1869,8 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g
return TRUE; /* "please don't remove this event (yet)" */
}
-static void start_event_run(const char *event_name,
- const char *success_msg
-) {
+static void start_event_run(const char *event_name)
+{
/* Start event asynchronously on the dump dir
* (synchronous run would freeze GUI until completion)
*/
@@ -1927,7 +1925,6 @@ static void start_event_run(const char *event_name,
evd->run_state = state;
evd->event_name = xstrdup(event_name);
evd->env_list = env_list;
- evd->success_msg = success_msg;
evd->event_log = strbuf_new();
evd->fd = state->command_out_fd;
@@ -2262,15 +2259,6 @@ static void highlight_forbidden(void)
static gint select_next_page_no(gint current_page_no, gpointer data);
-static void setup_and_start_event_run(const char *event_name)
-{
- start_event_run(event_name,
- /* this event is the last event from the chain */
- is_processing_finished() ? _("Processing finished.")
- : _("Processing finished, please proceed to the next step.")
- );
-}
-
static char *get_next_processed_event(GList **events_list)
{
if (!events_list || !*events_list)
@@ -2445,7 +2433,7 @@ static void on_page_prepare(GtkNotebook *assistant, GtkWidget *page, gpointer us
&& g_event_selected[0]
) {
clear_warnings();
- setup_and_start_event_run(g_event_selected);
+ start_event_run(g_event_selected);
}
}
--
1.8.2.1
10 years, 10 months
[RHEL6 LIBREPORT PATCH] fixed relro flags rhbz#812283
by Jiri Moskovcak
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
Conflicts:
src/client-python/Makefile.am
src/report-python/Makefile.am
---
src/client-python/Makefile.am | 6 +++---
src/report-python/Makefile.am | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/client-python/Makefile.am b/src/client-python/Makefile.am
index 4048d56..4da3aa6 100644
--- a/src/client-python/Makefile.am
+++ b/src/client-python/Makefile.am
@@ -19,11 +19,11 @@ _reportclient_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(PYTHON_CFLAGS) \
-D_GNU_SOURCE \
- -Wall -Wwrite-strings -Werror \
- -fPIE -Wl,-z,relro,now
+ -fPIE
_reportclient_la_LDFLAGS = \
-module \
-avoid-version \
- -export-symbols-regex init_reportclient
+ -export-symbols-regex init_reportclient \
+ -Wl,-z,relro -Wl,-z,now
_reportclient_la_LIBADD = \
../lib/libreport.la
diff --git a/src/report-python/Makefile.am b/src/report-python/Makefile.am
index 93ee625..e961eba 100644
--- a/src/report-python/Makefile.am
+++ b/src/report-python/Makefile.am
@@ -23,12 +23,12 @@ _pyreport_la_CPPFLAGS = \
$(GLIB_CFLAGS) \
$(PYTHON_CFLAGS) \
-D_GNU_SOURCE \
- -Wall -Wwrite-strings -Werror \
- -fPIE -Wl,-z,relro,now
+ -fPIE
_pyreport_la_LDFLAGS = \
-module \
-avoid-version \
- -export-symbols-regex init_pyreport
+ -export-symbols-regex init_pyreport \
+ -Wl,-z,relro -Wl,-z,now
_pyreport_la_LIBADD = \
../lib/libreport.la
--
1.8.2.1
10 years, 10 months
[LIBREPORT PATCH] pass the problem_dir to the screencasting application closes #165
by Jiri Moskovcak
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
---
src/gui-wizard-gtk/wizard.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index 151d879..9c867ca 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -3151,7 +3151,7 @@ static void on_btn_startcast(GtkWidget *btn, gpointer user_data)
(char **)args,
NULL,
/*env_vec:*/ NULL,
- /*dir:*/ NULL,
+ g_dump_dir_name,
/*uid (ignored):*/ 0
);
gtk_widget_hide(GTK_WIDGET(g_wnd_assistant));
@@ -3181,7 +3181,7 @@ static bool is_screencast_available()
(char **)args,
NULL,
/*env_vec:*/ NULL,
- /*dir:*/ NULL,
+ g_dump_dir_name,
/*uid (ignored):*/ 0
);
--
1.8.3.1
10 years, 10 months