summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Moskovcak <jmoskovc@redhat.com>2010-06-10 09:10:09 +0200
committerJiri Moskovcak <jmoskovc@redhat.com>2010-06-10 09:10:09 +0200
commitf1c1b935b89963d18552e0d0b7e81fb2341a61ea (patch)
tree7f8b6248a23e41dc5eb6c21f8af276c604f04128
parent11839b1f6e6e12731f3b779f554d4f2997a23c7d (diff)
parent5a8e8a4678b380026bee7b6838fd11272112c9f3 (diff)
downloadabrt-f1c1b935b89963d18552e0d0b7e81fb2341a61ea.tar.gz
abrt-f1c1b935b89963d18552e0d0b7e81fb2341a61ea.tar.xz
abrt-f1c1b935b89963d18552e0d0b7e81fb2341a61ea.zip
Merge branch 'master' of ssh://git.fedorahosted.org/git/abrt
-rw-r--r--.gitignore2
-rw-r--r--abrt.spec1
-rw-r--r--lib/Utils/Makefile.am3
-rw-r--r--lib/Utils/hooklib.cpp (renamed from src/Hooks/hooklib.cpp)0
-rw-r--r--lib/Utils/hooklib.h (renamed from src/Hooks/hooklib.h)0
-rw-r--r--po/it.po200
-rwxr-xr-xscripts/abrt-bz-dupchecker21
-rw-r--r--src/Daemon/Daemon.cpp5
-rw-r--r--src/Daemon/Makefile.am3
-rw-r--r--src/Daemon/dumpsocket.cpp573
-rw-r--r--src/Daemon/dumpsocket.h81
-rw-r--r--src/Hooks/Makefile.am28
-rw-r--r--src/Hooks/abrt-hook-python.cpp160
-rw-r--r--src/Hooks/abrt_exception_handler.py.in25
14 files changed, 797 insertions, 305 deletions
diff --git a/.gitignore b/.gitignore
index add9490b..9220ec38 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,13 +51,11 @@ src/CLI/abrt-cli
src/utils/abrt-backtrace
lib/Utils/backtrace_parser.c
lib/Utils/backtrace_parser.output
-src/Backtrace/*.bt
src/Daemon/abrtd
src/Gui/abrt.desktop
src/Hooks/abrt_exception_handler.py
src/Hooks/dumpoops
src/Hooks/abrt-hook-ccpp
-src/Hooks/abrt-hook-python
scripts/abrt-rate-backtrace
stamp-h1
x86_64/
diff --git a/abrt.spec b/abrt.spec
index e4aae962..3d190540 100644
--- a/abrt.spec
+++ b/abrt.spec
@@ -447,7 +447,6 @@ fi
%files addon-python
%defattr(-,root,root,-)
%config(noreplace) %{_sysconfdir}/%{name}/plugins/Python.conf
-%attr(4755, abrt, abrt) %{_libexecdir}/abrt-hook-python
%{_libdir}/%{name}/libPython.so*
%{python_site}/*.py*
%{python_site}/abrt.pth
diff --git a/lib/Utils/Makefile.am b/lib/Utils/Makefile.am
index 13144f68..f9979ec0 100644
--- a/lib/Utils/Makefile.am
+++ b/lib/Utils/Makefile.am
@@ -26,7 +26,8 @@ libABRTUtils_la_SOURCES = \
ABRTException.cpp \
backtrace.h backtrace.c \
backtrace_parser.y \
- strbuf.h strbuf.c
+ strbuf.h strbuf.c \
+ hooklib.h hooklib.cpp
libABRTUtils_la_CPPFLAGS = \
-Wall -Werror \
-I$(srcdir)/../../inc \
diff --git a/src/Hooks/hooklib.cpp b/lib/Utils/hooklib.cpp
index 0c00e75f..0c00e75f 100644
--- a/src/Hooks/hooklib.cpp
+++ b/lib/Utils/hooklib.cpp
diff --git a/src/Hooks/hooklib.h b/lib/Utils/hooklib.h
index 1651204f..1651204f 100644
--- a/src/Hooks/hooklib.h
+++ b/lib/Utils/hooklib.h
diff --git a/po/it.po b/po/it.po
index 9f38b083..55255bb1 100644
--- a/po/it.po
+++ b/po/it.po
@@ -10,10 +10,10 @@
# Andrea La Fauci <andrea.lafauci@weproudlymanage.com>, 2010.
msgid ""
msgstr ""
-"Project-Id-Version: abrt-fed14\n"
+"Project-Id-Version: ABRT\n"
"Report-Msgid-Bugs-To: jmoskovc@redhat.com\n"
"POT-Creation-Date: 2010-06-09 15:38+0200\n"
-"PO-Revision-Date: 2010-05-28 10:59+1000\n"
+"PO-Revision-Date: 2010-06-10 14:42+1000\n"
"Last-Translator: \n"
"Language-Team: <it@li.org>\n"
"MIME-Version: 1.0\n"
@@ -22,63 +22,61 @@ msgstr ""
"X-Generator: KBabel 1.11.4\n"
#: lib/Plugins/Catcut.cpp:61
-#, fuzzy
msgid "send_string: URL not specified"
-msgstr "FileTransfer: URL non specificato"
+msgstr "send_string: URL non specificato"
#: lib/Plugins/Catcut.cpp:77 lib/Plugins/Catcut.cpp:114
-#, fuzzy, c-format
+#, c-format
msgid "Sending failed, try it again: %s"
-msgstr "Invio archivio %s su %s"
+msgstr "Invio fallito, riprova: %s"
#: lib/Plugins/Catcut.cpp:95
-#, fuzzy
msgid "send_file: URL not specified"
-msgstr "FileTransfer: URL non specificato"
+msgstr "send_file: URL non specificato"
#: lib/Plugins/Catcut.cpp:99
-#, fuzzy, c-format
+#, c-format
msgid "Sending file %s to %s"
-msgstr "Invio archivio %s su %s"
+msgstr "Invio file %s a %s in corso"
#: lib/Plugins/Catcut.cpp:325
-#, fuzzy, c-format
+#, c-format
msgid "New bug id: %s"
-msgstr "Nuovo id del bug: %i"
+msgstr "Nuovo id del bug: %s"
#: lib/Plugins/Catcut.cpp:366
#, c-format
msgid "error returned by requestUpload: %s"
-msgstr ""
+msgstr "errore ritornato da requestUpload: %s"
#: lib/Plugins/Catcut.cpp:371
#, c-format
msgid "error returned by requestUpload: %d"
-msgstr ""
+msgstr "errore ritornato da requestUpload: %d"
#: lib/Plugins/Catcut.cpp:377
msgid "no URL returned by requestUpload, and no errno"
-msgstr ""
+msgstr "nessun URL ritornato da requestUpload, e nessun errno"
#: lib/Plugins/Catcut.cpp:382
#, c-format
msgid "requestUpload returned URL: %s"
-msgstr ""
+msgstr "URL ritornato da requestUpload: %s"
#: lib/Plugins/Catcut.cpp:402
#, c-format
msgid "Attaching (text): %s"
-msgstr ""
+msgstr "Inserimento (testo) in corso: %s"
#: lib/Plugins/Catcut.cpp:413 lib/Plugins/Catcut.cpp:431
#, c-format
msgid "rebased URL: %s"
-msgstr ""
+msgstr "URL modificato: %s"
#: lib/Plugins/Catcut.cpp:420
#, c-format
msgid "Attaching binary: %s"
-msgstr ""
+msgstr "Inserimento binario: %s"
#: lib/Plugins/Catcut.cpp:460 lib/Plugins/Bugzilla.cpp:655
msgid "Creating new bug..."
@@ -96,27 +94,24 @@ msgstr "Invio archivio %s su %s"
#: lib/Plugins/TicketUploader.cpp:130
#, c-format
msgid "Sending failed, trying again. %s"
-msgstr ""
+msgstr "Invio fallito, riprovo ancora. %s"
#: lib/Plugins/TicketUploader.cpp:192
-#, fuzzy
msgid "Creating a TicketUploader report..."
-msgstr "Creazione ed invio di un report in corso..."
+msgstr "Creazione di una notifica TicketUploader in corso..."
#: lib/Plugins/rhfastcheck.cpp:71
-#, fuzzy
msgid "Creating a signature..."
-msgstr "Creazione ed invio di un report in corso..."
+msgstr "Creazione di una firma in corso..."
#: lib/Plugins/rhticket.cpp:222
-#, fuzzy
msgid "Creating a new case..."
-msgstr "Creazione nuovo bug..."
+msgstr "Creazione di un nuovo caso..."
#: lib/Utils/make_descr.cpp:296
#, c-format
msgid "Binary file %s will not be reported"
-msgstr ""
+msgstr "Il file binario %s non verrà riportato"
#: src/CLI/CLI.cpp:68
#, c-format
@@ -129,6 +124,13 @@ msgid ""
"\tCrash Time : %s\n"
"\tCrash Count: %s\n"
msgstr ""
+"%u.\n"
+"\tUID : %s\n"
+"\tUUID : %s\n"
+"\tPackage : %s\n"
+"\tExecutable : %s\n"
+"\tCrash Time : %s\n"
+"\tCrash Count: %s\n"
#: src/CLI/CLI.cpp:154
#, c-format
@@ -150,126 +152,142 @@ msgid ""
"\tunique UUID prefix - the crash with matching UUID will be acted upon\n"
"\t@N - N'th crash (as displayed by --get-list-full) will be acted upon\n"
msgstr ""
+"Usage: %s [OPTION]\n"
+"\n"
+"Avvio:\n"
+"\t-V, --version\t\tmostra la versione di %s ed esci\n"
+"\t-?, --help\t\tstampa questo aiuto\n"
+"\n"
+"Azioni:\n"
+"\t--get-list\t\tstampa elenco dei crash non ancora riportati\n"
+"\t--get-list-full\t\tstampa elenco di tutti i crash\n"
+"\t--report CRASH_ID\tcrea ed invia riporto\n"
+"\t--report-always CRASH_ID crea ed invia riporto senza chiederlo\n"
+"\t--delete CRASH_ID\trimuovi il crash\n"
+"CRASH_ID possono essere:\n"
+"\tUID:UUID pair,\n"
+"\tprefisso UUID unico - il crash con un UUID corrispondente verrà esaminato\n"
+"\t@N - N'th crash (come mostrato da --get-list-full) verrà esaminato\n"
#: src/CLI/CLI.cpp:198
msgid "You must specify exactly one operation."
-msgstr ""
+msgstr "Specificare esattamente una operazione."
#: src/CLI/report.cpp:179
#, c-format
msgid "# This field is read only.\n"
-msgstr ""
+msgstr "# Questo campo è di sola lettura.\n"
#: src/CLI/report.cpp:199
msgid "# Describe the circumstances of this crash below."
-msgstr ""
+msgstr "# Descrivere qui di seguito le circostanza di questo crash."
#: src/CLI/report.cpp:201
msgid "# How to reproduce the crash?"
-msgstr ""
+msgstr "# Come riprodurre il crash?"
#: src/CLI/report.cpp:203
msgid ""
"# Backtrace\n"
"# Check that it does not contain any sensitive data such as passwords."
msgstr ""
+"# Backtrace\n"
+"# Controllare che non contenga alcun dato sensibile come ad esempio le password."
#: src/CLI/report.cpp:205
-#, fuzzy
msgid "# Architecture"
-msgstr "Architettura"
+msgstr "# Architettura"
#: src/CLI/report.cpp:206
-#, fuzzy
msgid "# Command line"
-msgstr "Cmdline"
+msgstr "# linea di comando"
#: src/CLI/report.cpp:207
-#, fuzzy
msgid "# Component"
-msgstr "Componente"
+msgstr "# Componente"
#: src/CLI/report.cpp:208
msgid "# Core dump"
-msgstr ""
+msgstr "# Core dump"
#: src/CLI/report.cpp:209
-#, fuzzy
msgid "# Executable"
-msgstr "Eseguibile"
+msgstr "# Eseguibile"
#: src/CLI/report.cpp:210
msgid "# Kernel version"
-msgstr ""
+msgstr "# versione del kernel"
#: src/CLI/report.cpp:211
-#, fuzzy
msgid "# Package"
-msgstr "Pacchetto"
+msgstr "# Pacchetto"
#: src/CLI/report.cpp:212
msgid "# Reason of crash"
-msgstr ""
+msgstr "# Motivo del crash"
#: src/CLI/report.cpp:213
msgid "# Release string of the operating system"
-msgstr ""
+msgstr "# Stringa della release del sistema operativo"
#: src/CLI/report.cpp:323
msgid "Terminal is dumb but no VISUAL nor EDITOR defined."
-msgstr ""
+msgstr "Il Terminale è su dumb ma non è stato definito alcun VISUAL o EDITOR."
#: src/CLI/report.cpp:411
msgid ""
"\n"
"The report has been updated."
msgstr ""
+"\n"
+"La notifica è stata aggiornata."
#: src/CLI/report.cpp:413
msgid ""
"\n"
"No changes were detected in the report."
msgstr ""
+"\n"
+"Nessuna modifica è stata rilevata nel report."
#: src/CLI/report.cpp:628
#, c-format
msgid "Wrong settings were detected for plugin %s.\n"
-msgstr ""
+msgstr "Rilevate impostazioni errate per il plugin %s.\n"
#: src/CLI/report.cpp:632
msgid "Enter your login: "
-msgstr ""
+msgstr "Inserire il login:"
#: src/CLI/report.cpp:638
msgid "Enter your password: "
-msgstr ""
+msgstr "Inserire la password:"
#: src/CLI/report.cpp:681
-#, fuzzy
msgid "Reporting..."
-msgstr "Report"
+msgstr "Notifica in corso..."
#: src/CLI/report.cpp:700
#, c-format
msgid "Report using %s? [y/N]: "
-msgstr ""
+msgstr "Notifica utilizzando %s? [s/N]: "
#: src/CLI/report.cpp:703
msgid "Skipping..."
-msgstr ""
+msgstr "Omissione in corso..."
#: src/CLI/report.cpp:720
#, c-format
msgid "Crash reported via %d plugins (%d errors)\n"
-msgstr ""
+msgstr "Crash notificato tramite %d plugin (%d errori)\n"
#: src/Daemon/CommLayerServerDBus.cpp:234
msgid "Comment is too long"
-msgstr ""
+msgstr "Il commento è troppo lungo"
#: src/Daemon/CommLayerServerDBus.cpp:238
msgid "'How to reproduce' is too long"
-msgstr ""
+msgstr "'How to reproduce' è troppo lungo"
#: src/Gui/ABRTExceptions.py:6
msgid "Another client is already running, trying to wake it."
@@ -277,8 +295,7 @@ msgstr "Un altro client è già in esecuzione, tento il ripristino."
#: src/Gui/ABRTExceptions.py:13
msgid "Got unexpected data from daemon (is the database properly updated?)."
-msgstr ""
-"Ricevuti dati inattesi dal demone (il database è aggiornato correttamente?)."
+msgstr "Ricevuti dati inattesi dal demone (il database è aggiornato correttamente?)."
#: src/Gui/ABRTPlugin.py:62
msgid "Not loaded plugins"
@@ -577,28 +594,25 @@ msgid "Error getting the report: %s"
msgstr "Errore nell'ottenere il report: %s"
#: src/Gui/ConfBackend.py:77
-#, fuzzy
msgid "Can't connect to Gnome Keyring daemon"
-msgstr "Impossibile connettersi a dbus del sistema"
+msgstr "Impossibile connettersi al demone Gnome Keyring"
#: src/Gui/ConfBackend.py:83
msgid "Can't get default keyring"
-msgstr ""
+msgstr "Impossibile acquisire il keyring predefinito"
#: src/Gui/ConfBackend.py:102 src/Gui/ConfBackend.py:118
-msgid ""
-"Access to gnome-keyring has been denied, plugins settings won't be saved."
-msgstr ""
+msgid "Access to gnome-keyring has been denied, plugins settings won't be saved."
+msgstr "L'accesso al gnome-keyring è stato negato, le impostazioni dei plugin non saranno salvati."
#: src/Gui/ConfBackend.py:152
#, python-format
-msgid ""
-"Access to gnome-keyring has been denied, can't load the settings for %s!"
-msgstr ""
+msgid "Access to gnome-keyring has been denied, can't load the settings for %s!"
+msgstr "L'accesso al gnome-keyring è stato negato, impossibile caricare le impostazioni per %s!."
#: src/Gui/ConfBackend.py:205
msgid "Access to gnome-keyring has been denied, can't load settings"
-msgstr ""
+msgstr "L'accesso al gnome-keyring è stato negato, impossibile caricare le impostazioni"
#: src/Gui/dialogs.glade:7
msgid "Report done"
@@ -610,25 +624,25 @@ msgstr "Log"
#: src/Gui/PluginsSettingsDialog.py:24
msgid "Can't load gui description for SettingsDialog!"
-msgstr ""
+msgstr "Impossibile caricare la descrizione della gui per SettingsDialog!"
#: src/Gui/PluginsSettingsDialog.py:41
-#, fuzzy
msgid "Name"
-msgstr "Nome:"
+msgstr "Nome"
#: src/Gui/PluginsSettingsDialog.py:148
msgid "Please select a plugin from the list to edit it's options."
-msgstr ""
+msgstr "Selezionare un plugin dall'elenco per modificare le opzioni."
#: src/Gui/PluginsSettingsDialog.py:156
-#, fuzzy, python-format
+#, python-format
msgid ""
"Error while opening plugin settings UI: \n"
"\n"
"%s"
msgstr ""
-"Errore durante il caricamento della dumplist.\n"
+"Errore durante l'apertura della UI per le impostazioni del plugin:\n"
+"\n"
"%s"
#: src/Gui/PluginSettingsUI.py:17
@@ -683,8 +697,7 @@ msgstr "<span fgcolor=\"blue\">Causa:</span>"
#: src/Gui/report.glade:331
msgid "I checked backtrace and removed sensitive data (passwords, etc)"
-msgstr ""
-"Ho controllato il backtrace ed ho rimosso i dati sensibili (password, etc)"
+msgstr "Ho controllato il backtrace ed ho rimosso i dati sensibili (password, etc)"
#: src/Gui/report.glade:369 src/Gui/CReporterAssistant.py:711
msgid "<b>Backtrace</b>"
@@ -839,9 +852,8 @@ msgid "GPG Keys"
msgstr "Chiavi GPG"
#: src/Gui/CReporterAssistant.py:273
-#, fuzzy
msgid "You should check backtrace for sensitive data"
-msgstr "E' necessario verificare il backtrace per trovare dati sensibili"
+msgstr "E' necessario verificare il backtrace per i dati sensibili"
#: src/Gui/CReporterAssistant.py:274
msgid "You must agree with sending the backtrace"
@@ -924,8 +936,7 @@ msgstr ""
"problema?"
#: src/Gui/CReporterAssistant.py:611
-msgid ""
-"Are there any comment you'd like to share with the software maintainers?"
+msgid "Are there any comment you'd like to share with the software maintainers?"
msgstr "Condividere alcun commento con i manutentori software?"
#: src/Gui/CReporterAssistant.py:630
@@ -945,8 +956,7 @@ msgid "Confirm and send report"
msgstr "Conferma ed invia il riporto"
#: src/Gui/CReporterAssistant.py:680
-msgid ""
-"Below is a summary of your bug report. Please click 'Apply' to submit it."
+msgid "Below is a summary of your bug report. Please click 'Apply' to submit it."
msgstr ""
"Di seguito viene riportato un sommario del bug report. Fare clic su "
"'Applica' per inviarlo."
@@ -992,9 +1002,8 @@ msgid "Click to view ..."
msgstr "Clicca per visualizzare ..."
#: src/Gui/CReporterAssistant.py:726
-#, fuzzy
msgid "<b>Steps to reproduce:</b>"
-msgstr "<b>Fasi da riprodurre:</b>"
+msgstr "<b>Fasi da eseguire:</b>"
#: src/Gui/CReporterAssistant.py:747
msgid "<b>Comments:</b>"
@@ -1005,9 +1014,8 @@ msgid "No comment provided!"
msgstr "Nessun commento fornito!"
#: src/Gui/CReporterAssistant.py:786
-#, fuzzy
msgid "Finished sending the bug report"
-msgstr "Termina l'invio del bug report"
+msgstr "Invio del bug report terminato"
#: src/Gui/CReporterAssistant.py:790
msgid "<b>Bug reports:</b>"
@@ -1015,19 +1023,18 @@ msgstr "<b>Bug Report:</b>"
#: src/Gui/settings_wizard.glade:7
msgid "Wrong Settings Detected"
-msgstr ""
+msgstr "Impostazioni errate rilevate"
#: src/Gui/settings_wizard.glade:40
msgid ""
"Wrong settings detected for some of the enabled reporter plugins, please use "
"the buttons below to open respective configuration and fix it before you "
"proceed, otherwise the reporting process can fail.\n"
-msgstr ""
+msgstr "Impostazioni errate rilevate per alcuni dei reporter plugin abilitati, usare i pulsanti sotto riportati per aprire la rispettiva configurazione e correggerla prima di procedere, in caso contrario il processo di notifica può fallire.\n"
#: src/Gui/settings_wizard.glade:71
-#, fuzzy
msgid "<b>Do you want to continue?</b>"
-msgstr "<b>Dove vuoi segnalare questo incidente?</b>"
+msgstr "<b>Desideri continuare?</b>"
#: src/Applet/Applet.cpp:88
#, c-format
@@ -1185,16 +1192,3 @@ msgstr "Esecuzione di sosreport: %s"
msgid "Done running sosreport"
msgstr "Esecuzione di sosreport completata"
-#, fuzzy
-#~ msgid ""
-#~ "Thank you for your bug report. It has been successfully submitted. You "
-#~ "can see the results below."
-#~ msgstr ""
-#~ "Grazie per l'invio del bug report. Il suo invio ha avuto successo. Per "
-#~ "visualizzare il bug report online usare il seguente indirizzo web:"
-
-#~ msgid "View and report application crashes"
-#~ msgstr "Visualizza e riporta i crash applicativi"
-
-#~ msgid "Not reported"
-#~ msgstr "Non riportato"
diff --git a/scripts/abrt-bz-dupchecker b/scripts/abrt-bz-dupchecker
index 89e13281..65e11531 100755
--- a/scripts/abrt-bz-dupchecker
+++ b/scripts/abrt-bz-dupchecker
@@ -54,7 +54,7 @@ bz = RHBugzilla()
bz.connect(options.bugzilla)
bz.login(options.user, options.password)
-buginfos = bz.query({'status_whiteboard_type':'allwordssubstr','status_whiteboard':'abrt_hash'})
+buginfos = bz.query({'status_whiteboard_type':'allwordssubstr','status_whiteboard':'abrt_hash', 'product':'Fedora'})
print "{0} bugs found.".format(len(buginfos))
@@ -122,7 +122,7 @@ for buginfo in buginfos:
if not downloaded:
continue
- command = ["./abrt-backtrace"]
+ command = ["abrt-backtrace"]
command.append(filename)
command.append("--single-thread")
command.append("--frame-depth=5")
@@ -178,7 +178,7 @@ for backtrace, components in database.items():
# Get the component owner
owner = "Failed to get component owner"
try:
- component_info = json.load(urllib.urlopen("https://admin.fedoraproject.org/pkgdb/packages/name/{0}?tg_format=json".format(component)))
+ component_info = json.load(urllib.urlopen("https://admin.fedoraproject.org/pkgdb/acls/name/{0}?tg_format=json".format(component)))
component_packages = component_info['packageListings']
component_f12 = filter(lambda x:x["collection"]["version"]=="12", component_packages)
if len(component_f12) == 1:
@@ -191,7 +191,7 @@ for backtrace, components in database.items():
# Close all bugs where it is appropriate.
if options.close:
- LIMIT = 1000
+ LIMIT = 10000 # infinite
counter = 0
for (component, owner, bugitems, backtrace) in dups:
# Find the master bug item
@@ -212,15 +212,24 @@ if options.close:
else:
return -1
+ # Sort the duplicates by the number of comments.
+ # Select the bug with the highest number of comments as the master bug.
+ # All other bugs without user comments will be closed as a duplicate of
+ # the master bug.
sorteditems = sorted(bugitems, commentCmp)
-
master = sorteditems[0]
+
+ # Check the master bug status AGAIN to make sure the bug is still opened.
+ bug = bz.getbug(int(master['id']))
+ if not bug.bug_status in ["NEW", "ASSIGNED"]:
+ continue
+
for item in sorteditems[1:]:
if item['comments'] > 2:
continue
- bug = bz.getbug(int(item['id']))
# Check the bug status AGAIN to make sure the bug is still opened.
+ bug = bz.getbug(int(item['id']))
if not bug.bug_status in ["NEW", "ASSIGNED"]:
continue
diff --git a/src/Daemon/Daemon.cpp b/src/Daemon/Daemon.cpp
index 3d8df570..d79d90a4 100644
--- a/src/Daemon/Daemon.cpp
+++ b/src/Daemon/Daemon.cpp
@@ -41,6 +41,7 @@
#include "CrashWatcher.h"
#include "DebugDump.h"
#include "Daemon.h"
+#include "dumpsocket.h"
using namespace std;
@@ -848,6 +849,9 @@ int main(int argc, char** argv)
throw 1;
pidfile_created = true;
+ /* Open socket to receive new crashes. */
+ dumpsocket_init();
+
/* Note: this already may process a few dbus messages,
* therefore it should be the last thing to initialize.
*/
@@ -899,6 +903,7 @@ int main(int argc, char** argv)
/* Error or INT/TERM. Clean up, in reverse order.
* Take care to not undo things we did not do.
*/
+ dumpsocket_shutdown();
if (pidfile_created)
unlink(VAR_RUN_PIDFILE);
if (lockfile_created)
diff --git a/src/Daemon/Makefile.am b/src/Daemon/Makefile.am
index 382f104f..56292150 100644
--- a/src/Daemon/Makefile.am
+++ b/src/Daemon/Makefile.am
@@ -10,7 +10,8 @@ abrtd_SOURCES = \
CommLayerServer.h CommLayerServer.cpp \
CommLayerServerDBus.h CommLayerServerDBus.cpp \
Daemon.h Daemon.cpp \
- Settings.h Settings.cpp
+ Settings.h Settings.cpp \
+ dumpsocket.h dumpsocket.cpp
abrtd_CPPFLAGS = \
-I$(srcdir)/../../inc \
-I$(srcdir)/../../lib/Utils \
diff --git a/src/Daemon/dumpsocket.cpp b/src/Daemon/dumpsocket.cpp
new file mode 100644
index 00000000..f1171ea8
--- /dev/null
+++ b/src/Daemon/dumpsocket.cpp
@@ -0,0 +1,573 @@
+/*
+ Copyright (C) 2010 ABRT team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "dumpsocket.h"
+#include "abrtlib.h"
+#include <glib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include "DebugDump.h"
+#include "CrashTypes.h"
+#include "ABRTException.h"
+#include "hooklib.h"
+#include "strbuf.h"
+
+#define SOCKET_FILE VAR_RUN"/abrt.socket"
+#define SOCKET_PERMISSION 0666
+
+/* Maximal length of backtrace. */
+#define MAX_BACKTRACE_SIZE (1024*1024)
+
+/* Amount of data received from one client for a message before reporting error. */
+#define MAX_MESSAGE_SIZE (4*MAX_BACKTRACE_SIZE)
+
+/* Maximum number of simultaneously opened client connections. */
+#define MAX_CLIENT_COUNT 10
+
+/* Interval between checks of client halt, in seconds. */
+#define CLIENT_CHECK_INTERVAL 10
+
+/* Interval with no data received from client, after which the client is
+ considered halted, in seconds. */
+#define CLIENT_HALT_INTERVAL 10
+
+/* Maximal number of characters read from socket at once. */
+#define INPUT_BUFFER_SIZE 1024
+
+static GIOChannel *channel = NULL;
+static guint channel_cb_id = 0;
+static int client_count = 0;
+
+/* Information about single socket session. */
+struct client
+{
+ /* Client user id */
+ uid_t uid;
+ /* Buffer for incomplete incoming messages. */
+ GByteArray *messagebuf;
+ /* Executable. */
+ char *executable;
+ /* Process ID. */
+ int pid;
+ char *backtrace;
+ /* Python, Ruby etc. */
+ char *analyzer;
+ /* Directory base name: python (or pyhook), ruby etc. */
+ char *basename;
+ /* Crash reason.
+ * Python example: "CCMainWindow.py:1:<module>:ZeroDivisionError:
+ * integer division or modulo by zero"
+ */
+ char *reason;
+ /* Last time some data were received over the socket
+ * from the client.
+ */
+ time_t lastwrite;
+ /* Timer checking client halt. */
+ guint timer_id;
+ /* Client socket callback id. */
+ guint socket_id;
+ /* Client socket channel */
+ GIOChannel *channel;
+};
+
+static gboolean server_socket_cb(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data);
+
+/* Releases all memory that belongs to a client session. */
+static void client_free(struct client *client)
+{
+ /* Delete the uncompleted message if there is some. */
+ g_byte_array_free(client->messagebuf, TRUE);
+ free(client->executable);
+ free(client->backtrace);
+ free(client->analyzer);
+ free(client->basename);
+ free(client->reason);
+ g_source_remove(client->timer_id);
+ g_source_remove(client->socket_id);
+ g_io_channel_unref(client->channel);
+ free(client);
+ --client_count;
+ if (!channel_cb_id)
+ {
+ channel_cb_id = g_io_add_watch(channel,
+ (GIOCondition)(G_IO_IN | G_IO_PRI),
+ (GIOFunc)server_socket_cb,
+ NULL);
+ if (!channel_cb_id)
+ perror_msg_and_die("dumpsocket: Can't add socket watch");
+ }
+}
+
+/* Callback called by glib main loop at regular intervals when
+ some client is connected. */
+static gboolean client_check_cb(gpointer data)
+{
+ struct client *client = (struct client*)data;
+ if (time(NULL) - client->lastwrite > CLIENT_HALT_INTERVAL)
+ {
+ log("dumpsocket: client socket timeout reached, closing connection");
+ client_free(client);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/* Caller is responsible to free() the returned value. */
+static char *giocondition_to_string(GIOCondition condition)
+{
+ struct strbuf *strbuf = strbuf_new();
+ if (condition & G_IO_HUP)
+ strbuf_append_str(strbuf, "G_IO_HUP | ");
+ if (condition & G_IO_ERR)
+ strbuf_append_str(strbuf, "G_IO_ERR | ");
+ if (condition & G_IO_NVAL)
+ strbuf_append_str(strbuf, "G_IO_NVAL | ");
+ if (condition & G_IO_IN)
+ strbuf_append_str(strbuf, "G_IO_IN | ");
+ if (condition & G_IO_OUT)
+ strbuf_append_str(strbuf, "G_IO_OUT | ");
+ if (condition & G_IO_PRI)
+ strbuf_append_str(strbuf, "G_IO_PRI | ");
+ if (strbuf->len == 0)
+ strbuf_append_str(strbuf, "none");
+ else
+ {
+ /* remove the last " | " */
+ strbuf->len -= 3;
+ strbuf->buf[strbuf->len] = '\0';
+ }
+ char *result = strbuf->buf;
+ strbuf_free_nobuf(strbuf);
+ return result;
+}
+
+/* Create a new debug dump from client session.
+ * Caller must ensure that all fields in struct client
+ * are properly filled.
+ */
+static void create_debug_dump(struct client *client)
+{
+ /* Create temp directory with the debug dump.
+ This directory is renamed to final directory name after
+ all files have been stored into it.
+ */
+ char *path = xasprintf(DEBUG_DUMPS_DIR"/%s-%ld-%u.new",
+ client->basename,
+ (long)time(NULL),
+ client->pid);
+ /* No need to check the path length, as all variables used are limited, and dd.Create()
+ fails if the path is too long. */
+
+ CDebugDump dd;
+ try {
+ dd.Create(path, client->uid);
+ } catch (CABRTException &e) {
+ dd.Delete();
+ dd.Close();
+ error_msg_and_die("dumpsocket: Error while creating crash dump %s: %s", path, e.what());
+ }
+
+ dd.SaveText(FILENAME_ANALYZER, client->analyzer);
+ dd.SaveText(FILENAME_EXECUTABLE, client->executable);
+ dd.SaveText(FILENAME_BACKTRACE, client->backtrace);
+ dd.SaveText(FILENAME_REASON, client->reason);
+
+ /* Obtain and save the command line. */
+ char *cmdline = get_cmdline(client->pid); // never NULL
+ dd.SaveText(FILENAME_CMDLINE, cmdline);
+ free(cmdline);
+
+ /* Store id of the user whose application crashed. */
+ char uid_str[sizeof(long) * 3 + 2];
+ sprintf(uid_str, "%lu", (long)client->uid);
+ dd.SaveText(CD_UID, uid_str);
+
+ dd.Close();
+
+ /* Move the completely created debug dump to
+ final directory. */
+ char *newpath = xstrndup(path, strlen(path) - strlen(".new"));
+ if (rename(path, newpath) == 0)
+ strcpy(path, newpath);
+ free(newpath);
+
+ log("dumpsocket: Saved %s crash dump of pid %u to %s",
+ client->analyzer, client->pid, path);
+
+ /* Handle free space checking. */
+ unsigned maxCrashReportsSize = 0;
+ parse_conf(NULL, &maxCrashReportsSize, NULL, NULL);
+ if (maxCrashReportsSize > 0)
+ {
+ check_free_space(maxCrashReportsSize);
+ trim_debug_dumps(maxCrashReportsSize, path);
+ }
+
+ free(path);
+}
+
+/* Checks if a string contains only printable characters. */
+static bool printable_str(const char *str)
+{
+ do {
+ if ((unsigned char)(*str) < ' ' || *str == 0x7f)
+ return false;
+ str++;
+ } while (*str);
+ return true;
+}
+
+/* Checks if a string has certain prefix. */
+static bool starts_with(const char *str, const char *start)
+{
+ return strncmp(str, start, strlen(start)) == 0;
+}
+
+/* @returns
+ * Caller is responsible to call free() on the returned
+ * pointer.
+ * If NULL is returned, string extraction failed.
+ */
+static char *try_to_get_string(const char *message,
+ const char *tag,
+ size_t max_len,
+ bool printable,
+ bool allow_slashes)
+{
+ if (!starts_with(message, tag))
+ return NULL;
+
+ const char *contents = message + strlen(tag);
+ if ((printable && !printable_str(contents)) ||
+ (!allow_slashes && strchr(contents, '/')))
+ {
+ error_msg("dumpsocket: Received %s contains invalid characters -> skipping", tag);
+ return NULL;
+ }
+
+ if (strlen(contents) > max_len)
+ {
+ char *max_len_str = g_format_size_for_display(max_len);
+ error_msg("dumpsocket: Received %s too long -> trimming to %s", tag, max_len_str);
+ g_free(max_len_str);
+ }
+
+ return xstrndup(contents, max_len);
+}
+
+/* Handles a message received from client over socket. */
+static void process_message(struct client *client, const char *message)
+{
+/* @param tag
+ * The message identifier. Message starting with it
+ * is handled by this macro.
+ * @param field
+ * Member in struct client, which should be filled by
+ * the field contents.
+ * @param max_len
+ * Maximum length of the field in bytes.
+ * Exceeding bytes are trimmed.
+ * @param printable
+ * Whether to limit the field contents to ASCII only.
+ * @param allow_slashes
+ * Whether to allow slashes to be a part of input.
+ */
+#define HANDLE_INCOMING_STRING(tag, field, max_len, printable, allow_slashes) \
+ char *field = try_to_get_string(message, tag, max_len, printable, allow_slashes); \
+ if (field) \
+ { \
+ free(client->field); \
+ client->field = field; \
+ return; \
+ }
+
+ HANDLE_INCOMING_STRING("EXECUTABLE=", executable, PATH_MAX, true, true);
+ HANDLE_INCOMING_STRING("BACKTRACE=", backtrace, MAX_BACKTRACE_SIZE, false, true);
+ HANDLE_INCOMING_STRING("BASENAME=", basename, 100, true, false);
+ HANDLE_INCOMING_STRING("ANALYZER=", analyzer, 100, true, true);
+ HANDLE_INCOMING_STRING("REASON=", reason, 512, false, true);
+
+#undef HANDLE_INCOMING_STRING
+
+ /* PID is not handled as a string, we convert it to pid_t. */
+ if (starts_with(message, "PID="))
+ {
+ /* xatou() cannot be used here, because it would
+ * kill whole daemon by non-numeric string.
+ */
+ char *endptr;
+ errno = 0;
+ const char *nptr = message + strlen("PID=");
+ unsigned long number = strtoul(nptr, &endptr, 10);
+ /* pid == 0 is error, the lowest PID is 1. */
+ if (errno || nptr == endptr || *endptr != '\0' || number > UINT_MAX || number == 0)
+ {
+ error_msg("dumpsocket: invalid PID received -> ignoring");
+ return;
+ }
+ client->pid = number;
+ return;
+ }
+
+ /* Creates debug dump if all fields were already provided. */
+ if (starts_with(message, "DONE"))
+ {
+ if (client->pid == 0 ||
+ client->backtrace == NULL ||
+ client->executable == NULL ||
+ client->analyzer == NULL ||
+ client->basename == NULL ||
+ client->reason == NULL)
+ {
+ error_msg("dumpsocket: DONE received, but some data are missing -> ignoring");
+ return;
+ }
+
+ create_debug_dump(client);
+ return;
+ }
+}
+
+/* Callback called by glib main loop when ABRT receives data that have
+ * been written to the socket by some client.
+ */
+static gboolean client_socket_cb(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ struct client *client = (struct client*)data;
+
+ /* Detailed logging, useful for debugging. */
+ if (g_verbose >= 3)
+ {
+ char *cond = giocondition_to_string(condition);
+ log("dumpsocket: client condition %s", cond);
+ free(cond);
+ }
+
+ /* Handle incoming data. */
+ if (condition & (G_IO_IN | G_IO_PRI))
+ {
+ guint loop = client->messagebuf->len;
+ gsize len;
+ gchar buf[INPUT_BUFFER_SIZE];
+ GError *err = NULL;
+ /* Read data in chunks of size INPUT_BUFFER_SIZE. This allows to limit the number of
+ bytes received (to prevent memory exhaustion). */
+ do {
+ GIOStatus result = g_io_channel_read_chars(source, buf, INPUT_BUFFER_SIZE, &len, &err);
+ if (result == G_IO_STATUS_ERROR)
+ {
+ g_assert(err);
+ error_msg("dumpsocket: Error while reading data from client socket: %s", err->message);
+ g_error_free(err);
+ client_free(client);
+ return FALSE;
+ }
+
+ if (g_verbose >= 3)
+ log("dumpsocket: received %zu bytes of data", len);
+
+ /* Append the incoming data to the message buffer. */
+ g_byte_array_append(client->messagebuf, (guint8*)buf, len);
+
+ if (client->messagebuf->len > MAX_MESSAGE_SIZE)
+ {
+ error_msg("dumpsocket: Message too long.");
+ client_free(client);
+ return FALSE;
+ }
+ } while (len > 0);
+
+ /* Check, if we received a complete message now. */
+ for (; loop < client->messagebuf->len; ++loop)
+ {
+ if (client->messagebuf->data[loop] != '\0')
+ continue;
+
+ VERB3 log("dumpsocket: Processing message: %s",
+ client->messagebuf->data);
+
+ /* Process the message. */
+ process_message(client, (char*)client->messagebuf->data);
+ /* Remove the message including the ending \0 */
+ g_byte_array_remove_range(client->messagebuf, 0, loop + 1);
+ loop = 0;
+ }
+
+ /* Update the last write access time */
+ client->lastwrite = time(NULL);
+ }
+
+ /* Handle socket disconnection.
+ It is important to do it after handling G_IO_IN, because sometimes
+ G_IO_HUP comes together with G_IO_IN. It means that some data arrived
+ and then the socket has been closed.
+ */
+ if (condition & (G_IO_HUP | G_IO_ERR | G_IO_NVAL))
+ {
+ log("dumpsocket: Socket client disconnected");
+ client_free(client);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/* If the status indicates failure, report it. */
+static void check_status(GIOStatus status, GError *err, const char *operation)
+{
+ if (status == G_IO_STATUS_NORMAL)
+ return;
+
+ if (err)
+ {
+ error_msg("dumpsocket: Error while %s: %s", operation, err->message);
+ g_error_free(err);
+ }
+ else
+ error_msg("dumpsocket: Error while %s", operation);
+}
+
+/* Initializes a new client session data structure. */
+static struct client *client_new(int socket)
+{
+ struct client *client = (struct client*)xzalloc(sizeof(struct client));
+
+ /* Get credentials for the socket client. */
+ struct ucred cr;
+ socklen_t crlen = sizeof(struct ucred);
+ if (0 != getsockopt(socket, SOL_SOCKET, SO_PEERCRED, &cr, &crlen))
+ perror_msg_and_die("dumpsocket: Failed to get client uid");
+ if (crlen != sizeof(struct ucred))
+ perror_msg_and_die("dumpsocket: Failed to get client uid (crlen)");
+ client->uid = cr.uid;
+
+ client->messagebuf = g_byte_array_new();
+ client->lastwrite = time(NULL);
+
+ close_on_exec_on(socket);
+
+ /* Create client IO channel. */
+ client->channel = g_io_channel_unix_new(socket);
+ g_io_channel_set_close_on_unref(client->channel, TRUE);
+
+ /* Set nonblocking access. */
+ GError *err = NULL;
+ GIOStatus status = g_io_channel_set_flags(client->channel, G_IO_FLAG_NONBLOCK, &err);
+ check_status(status, err, "setting NONBLOCK flag");
+
+ /* Disable channel encoding to protect binary data. */
+ err = NULL;
+ status = g_io_channel_set_encoding(client->channel, NULL, &err);
+ check_status(status, err, "setting encoding");
+
+ /* Start timer to check the client problems. */
+ client->timer_id = g_timeout_add_seconds(CLIENT_CHECK_INTERVAL, client_check_cb, client);
+ if (!client->timer_id)
+ error_msg_and_die("dumpsocket: Can't add client timer");
+
+ /* Register client callback. */
+ client->socket_id = g_io_add_watch(client->channel,
+ (GIOCondition)(G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL),
+ (GIOFunc)client_socket_cb,
+ client);
+ if (!client->socket_id)
+ error_msg_and_die("dumpsocket: Can't add client socket watch");
+
+ ++client_count;
+ return client;
+}
+
+/* Callback called by glib main loop when a client newly opens ABRT's socket. */
+static gboolean server_socket_cb(GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ /* Check the limit for number of simultaneously attached clients. */
+ if (client_count >= MAX_CLIENT_COUNT)
+ {
+ error_msg("dumpsocket: Too many clients, refusing connection.");
+ /* To avoid infinite loop caused by the descriptor in "ready" state,
+ the callback must be disabled.
+ It is added back in client_free(). */
+ g_source_remove(channel_cb_id);
+ channel_cb_id = 0;
+ return TRUE;
+ }
+
+ struct sockaddr_un remote;
+ socklen_t len = sizeof(remote);
+ int socket = accept(g_io_channel_unix_get_fd(source),
+ (struct sockaddr*)&remote, &len);
+ if (socket == -1)
+ {
+ perror_msg("dumpsocket: Server can not accept client");
+ return TRUE;
+ }
+
+ log("dumpsocket: New client connected");
+ client_new(socket);
+ return TRUE;
+}
+
+/* Initializes the dump socket, usually in /var/run directory
+ * (the path depends on compile-time configuration).
+ */
+void dumpsocket_init()
+{
+ struct sockaddr_un local;
+ unlink(SOCKET_FILE); /* not caring about the result */
+ int socketfd = xsocket(AF_UNIX, SOCK_STREAM, 0);
+ close_on_exec_on(socketfd);
+ memset(&local, 0, sizeof(local));
+ local.sun_family = AF_UNIX;
+ strcpy(local.sun_path, SOCKET_FILE);
+ xbind(socketfd, (struct sockaddr*)&local, sizeof(local));
+ xlisten(socketfd, MAX_CLIENT_COUNT);
+
+ if (chmod(SOCKET_FILE, SOCKET_PERMISSION) != 0)
+ perror_msg_and_die("dumpsocket: failed to chmod socket file");
+
+ channel = g_io_channel_unix_new(socketfd);
+ g_io_channel_set_close_on_unref(channel, TRUE);
+ channel_cb_id = g_io_add_watch(channel,
+ (GIOCondition)(G_IO_IN | G_IO_PRI),
+ (GIOFunc)server_socket_cb,
+ NULL);
+ if (!channel_cb_id)
+ perror_msg_and_die("dumpsocket: Can't add socket watch");
+}
+
+/* Releases all resources used by dumpsocket. */
+void dumpsocket_shutdown()
+{
+ /* Set everything to pre-initialization state. */
+ if (channel)
+ {
+ /* This one is for g_io_add_watch. */
+ if (channel_cb_id)
+ g_source_remove(channel_cb_id);
+ /* This one is for g_io_channel_unix_new. */
+ g_io_channel_unref(channel);
+ channel = NULL;
+ }
+}
diff --git a/src/Daemon/dumpsocket.h b/src/Daemon/dumpsocket.h
new file mode 100644
index 00000000..e5b79d60
--- /dev/null
+++ b/src/Daemon/dumpsocket.h
@@ -0,0 +1,81 @@
+/*
+ Copyright (C) 2010 ABRT team
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef ABRT_DUMPSOCKET_H
+#define ABRT_DUMPSOCKET_H
+
+/*
+Unix socket in ABRT daemon for creating new dump directories.
+
+Why to use socket for creating dump dirs? Security. When a Python
+script throwns unexpected exception, ABRT handler catches it, running
+as a part of that broken Python application. The application is running
+with certain SELinux privileges, for example it can not execute other
+programs, or to create files in /var/cache or anything else required
+to properly fill a dump directory. Adding these privileges to every
+application would weaken the security.
+The most suitable solution is for the Python application
+to open a socket where ABRT daemon is listening, write all relevant
+data to that socket, and close it. ABRT daemon handles the rest.
+
+** Protocol
+
+Initializing new dump:
+open /var/run/abrt.socket
+
+Providing dump data (hook writes to the socket):
+-> "PID="
+ number 0 - PID_MAX (/proc/sys/kernel/pid_max)
+ \0
+-> "EXECUTABLE="
+ string (maximum length ~MAX_PATH)
+ \0
+-> "BACKTRACE="
+ string (maximum length 1 MB)
+ \0
+-> "ANALYZER="
+ string (maximum length 100 bytes)
+ \0
+-> "BASENAME="
+ string (maximum length 100 bytes, no slashes)
+ \0
+-> "REASON="
+ string (maximum length 512 bytes)
+ \0
+
+Finalizing dump creation:
+-> "DONE"
+ \0
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initializes the dump socket, usually in /var/run directory
+ * (the path depends on compile-time configuration).
+ */
+extern void dumpsocket_init();
+
+/* Releases all resources used by dumpsocket. */
+extern void dumpsocket_shutdown();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/Hooks/Makefile.am b/src/Hooks/Makefile.am
index 6845c72c..eec2cd11 100644
--- a/src/Hooks/Makefile.am
+++ b/src/Hooks/Makefile.am
@@ -1,10 +1,8 @@
-libexec_PROGRAMS = abrt-hook-ccpp abrt-hook-python
+libexec_PROGRAMS = abrt-hook-ccpp
bin_PROGRAMS = dumpoops
# abrt-hook-ccpp
-abrt_hook_ccpp_SOURCES = \
- abrt-hook-ccpp.cpp \
- hooklib.h hooklib.cpp
+abrt_hook_ccpp_SOURCES = abrt-hook-ccpp.cpp
abrt_hook_ccpp_CPPFLAGS = \
-I$(srcdir)/../../inc \
-I$(srcdir)/../../lib/Utils \
@@ -16,8 +14,7 @@ abrt_hook_ccpp_LDADD = \
../../lib/Utils/libABRTUtils.la
# dumpoops
-dumpoops_SOURCES = \
- dumpoops.cpp
+dumpoops_SOURCES = dumpoops.cpp
dumpoops_CPPFLAGS = \
-I$(srcdir)/../../inc \
-I$(srcdir)/../../lib/Utils \
@@ -33,28 +30,15 @@ dumpoops_LDADD = \
../../lib/Utils/libABRTUtils.la \
../../lib/Utils/libABRTdUtils.la
-# abrt-hook-python
-abrt_hook_python_SOURCES = \
- abrt-hook-python.cpp \
- hooklib.h hooklib.cpp
-abrt_hook_python_CPPFLAGS = \
- -I$(srcdir)/../../inc \
- -I$(srcdir)/../../lib/Utils \
- -DDEBUG_DUMPS_DIR=\"$(DEBUG_DUMPS_DIR)\" \
- -DCONF_DIR=\"$(CONF_DIR)\" \
- -DVAR_RUN=\"$(VAR_RUN)\" \
- -D_GNU_SOURCE
-abrt_hook_python_LDADD = \
- ../../lib/Utils/libABRTUtils.la
-
python_PYTHON = abrt.pth abrt_exception_handler.py
EXTRA_DIST = abrt_exception_handler.py.in $(man_MANS)
CLEANFILES := $(notdir $(wildcard *~)) $(notdir $(wildcard *\#)) $(notdir $(wildcard \.\#*)) $(notdir $(wildcard *.pyc))
+# Must be synchronized with another sed call below.
abrt_exception_handler.py:
- sed s,@DEBUG_DUMP_DIR@,$(DEBUG_DUMPS_DIR),g abrt_exception_handler.py.in > abrt_exception_handler.py
+ sed s,\@VAR_RUN\@,\"$(VAR_RUN)\",g abrt_exception_handler.py.in > abrt_exception_handler.py
# RPM fix: we need to regenerate abrt_exception_handler.py, because it has the default ddir
install-data-local:
- sed s,@DEBUG_DUMP_DIR@,$(DEBUG_DUMPS_DIR),g abrt_exception_handler.py.in > abrt_exception_handler.py
+ sed s,\@VAR_RUN\@,\"$(VAR_RUN)\",g abrt_exception_handler.py.in > abrt_exception_handler.py
diff --git a/src/Hooks/abrt-hook-python.cpp b/src/Hooks/abrt-hook-python.cpp
deleted file mode 100644
index 5f2dc809..00000000
--- a/src/Hooks/abrt-hook-python.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- abrt-hook-python.cpp - writes data to the /var/spool/abrt directory
- with SUID bit
-
- Copyright (C) 2009 RedHat inc.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License along
- with this program; if not, write to the Free Software Foundation, Inc.,
- 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-*/
-#include <getopt.h>
-#include <syslog.h>
-// We can easily get rid of abrtlib (libABRTUtils.so) usage in this file,
-// but DebugDump will pull it in anyway
-#include "abrtlib.h"
-#include "hooklib.h"
-#include "DebugDump.h"
-#include "CrashTypes.h"
-#include "ABRTException.h"
-#if HAVE_CONFIG_H
-# include <config.h>
-#endif
-
-#define MAX_BT_SIZE (1024*1024)
-#define MAX_BT_SIZE_STR "1 MB"
-
-static char *pid;
-static char *executable;
-
-static bool printable_str(const char *str)
-{
- do {
- if ((unsigned char)(*str) < ' ' || *str == 0x7f)
- return false;
- str++;
- } while (*str);
- return true;
-}
-
-int main(int argc, char** argv)
-{
- // Parse options
- static const struct option longopts[] = {
- // name , has_arg , flag, val
- { "pid" , required_argument, NULL, 'p' },
- { "executable", required_argument, NULL, 'e' },
- { 0 },
- };
- int opt;
- while ((opt = getopt_long(argc, argv, "p:e:u:l:", longopts, NULL)) != -1)
- {
- switch (opt)
- {
- case 'p':
- pid = optarg;
- break;
- case 'e':
- executable = optarg;
- break;
- default:
- usage:
- error_msg_and_die(
- "Usage: abrt-hook-python [OPTIONS] <BACKTRACE\n"
- "\nOptions:\n"
- " -p,--pid PID PID of process that caused the crash\n"
- " -p,--executable PATH absolute path to the program that crashed\n"
- );
- }
- }
- if (!pid || !executable)
- goto usage;
- if (strlen(executable) > PATH_MAX || !printable_str(executable))
- goto usage;
- // pid string is sanitized later by xatou()
-
- openlog("abrt", LOG_PID, LOG_DAEMON);
- logmode = LOGMODE_SYSLOG;
-
- // Error if daemon is not running
- if (!daemon_is_ok())
- error_msg_and_die("daemon is not running, python crash dump aborted");
-
- unsigned setting_MaxCrashReportsSize = 0;
- parse_conf(NULL, &setting_MaxCrashReportsSize, NULL, NULL);
- if (setting_MaxCrashReportsSize > 0)
- {
- check_free_space(setting_MaxCrashReportsSize);
- }
-
- // Read the backtrace from stdin
- char *bt = (char*)xmalloc(MAX_BT_SIZE);
- ssize_t len = full_read(STDIN_FILENO, bt, MAX_BT_SIZE-1);
- if (len < 0)
- {
- perror_msg_and_die("read error");
- }
- bt[len] = '\0';
- if (len == MAX_BT_SIZE-1)
- {
- error_msg("backtrace size limit exceeded, trimming to " MAX_BT_SIZE_STR);
- }
-
- // This also checks that pid is a valid numeric string
- char *cmdline = get_cmdline(xatou(pid)); // never NULL
-
- // Create directory with the debug dump
- char path[PATH_MAX];
- unsigned path_len = snprintf(path, sizeof(path), DEBUG_DUMPS_DIR"/pyhook-%ld-%s.new",
- (long)time(NULL), pid);
- if (path_len >= sizeof(path))
- exit(1);
- CDebugDump dd;
- try {
- dd.Create(path, getuid());
- } catch (CABRTException &e) {
- dd.Delete();
- dd.Close();
- error_msg_and_die("error while creating crash dump %s: %s", path, e.what());
- }
-
- dd.SaveText(FILENAME_ANALYZER, "Python");
- dd.SaveText(FILENAME_EXECUTABLE, executable);
- dd.SaveText(FILENAME_BACKTRACE, bt);
- // python handler puts a short(er) crash descr in 1st line. Example:
- // "CCMainWindow.py:1:<module>:ZeroDivisionError: integer division or modulo by zero"
- strchrnul(bt, '\n')[0] = '\0';
- dd.SaveText(FILENAME_REASON, bt);
- free(bt);
- dd.SaveText(FILENAME_CMDLINE, cmdline);
- free(cmdline);
- char uid[sizeof(long) * 3 + 2];
- sprintf(uid, "%lu", (long)getuid());
- dd.SaveText(CD_UID, uid);
-
- dd.Close();
-
- char *newpath = xstrndup(path, path_len - (sizeof(".new")-1));
- if (rename(path, newpath) == 0)
- strcpy(path, newpath);
- free(newpath);
-
- log("saved python crash dump of pid %s to %s", pid, path);
-
- if (setting_MaxCrashReportsSize > 0)
- {
- trim_debug_dumps(setting_MaxCrashReportsSize, path);
- }
-
- return 0;
-}
diff --git a/src/Hooks/abrt_exception_handler.py.in b/src/Hooks/abrt_exception_handler.py.in
index a4bc93d5..99817296 100644
--- a/src/Hooks/abrt_exception_handler.py.in
+++ b/src/Hooks/abrt_exception_handler.py.in
@@ -19,27 +19,34 @@
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
"""
-Module for a userfriendly exception handling
+Module for the ABRT exception handling hook
"""
import sys
import os
import syslog
import subprocess
+import socket
def write_dump(pid, tb):
executable = "Exception raised from python shell"
if sys.argv[0]:
executable = os.path.abspath(sys.argv[0])
- command = ["/usr/libexec/abrt-hook-python"]
- command.append("--pid=%s" % pid)
- command.append("--executable=%s" % executable)
-
- helper = subprocess.Popen(command, stdin=subprocess.PIPE)
- helper.communicate(tb)
- helper.wait()
-
+ # Open ABRT daemon's socket and write data to it.
+ s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
+ s.connect(@VAR_RUN@ + "/abrt.socket")
+ s.sendall("PID=%s\0" % pid)
+ s.sendall("EXECUTABLE=%s\0" % executable)
+ s.sendall("ANALYZER=Python\0")
+ s.sendall("BASENAME=pyhook\0")
+ # This handler puts a short(er) crash descr in 1st line of the backtrace.
+ # Example:
+ # CCMainWindow.py:1:<module>:ZeroDivisionError: integer division or modulo by zero
+ s.sendall("REASON=%s\0" % tb.splitlines()[0])
+ s.sendall("BACKTRACE=%s\0" % tb)
+ s.sendall("DONE\0")
+ s.close()
def handleMyException((etype, value, tb)):
"""