Signed-off-by: Nikola Pajkovsky npajkovs@redhat.com --- doc/CodingStyle | 64 ------------------- doc/DESIGN | 147 ------------------------------------------ doc/HOW_TO_TEST | 41 ------------ doc/IMPLEMENTATION | 89 -------------------------- doc/INTERPRETED_LANGUAGES | 113 --------------------------------- doc/PLUGINS-HOWTO | 155 --------------------------------------------- doc/coding-style | 64 +++++++++++++++++++ doc/design | 147 ++++++++++++++++++++++++++++++++++++++++++ doc/how-to-test | 41 ++++++++++++ doc/implementation | 89 ++++++++++++++++++++++++++ doc/interpreted-languages | 113 +++++++++++++++++++++++++++++++++ doc/plugins-howto | 155 +++++++++++++++++++++++++++++++++++++++++++++ 12 files changed, 609 insertions(+), 609 deletions(-) delete mode 100644 doc/CodingStyle delete mode 100644 doc/DESIGN delete mode 100644 doc/HOW_TO_TEST delete mode 100644 doc/IMPLEMENTATION delete mode 100644 doc/INTERPRETED_LANGUAGES delete mode 100644 doc/PLUGINS-HOWTO create mode 100644 doc/coding-style create mode 100644 doc/design create mode 100644 doc/how-to-test create mode 100644 doc/implementation create mode 100644 doc/interpreted-languages create mode 100644 doc/plugins-howto
diff --git a/doc/CodingStyle b/doc/CodingStyle deleted file mode 100644 index 3a254b7..0000000 --- a/doc/CodingStyle +++ /dev/null @@ -1,64 +0,0 @@ -Coding style used in abrt -================================= - -1. Class --------- -1.1 Class has to start with 'C' - -1.2 Method ------------ -1.2.1 method starts witch a capital letter -1.2.2 method name can contain only letters -1.2.3 parameter of a method has to start with the letter 'p' - -1.3 Attribute -------------- -1.3.1 non-float attribute has to start with "m_n" -1.3.2 float attribute has to start with "m_f" -1.3.3 double attribute has to start with "m_d" -1.3.4 bool attribute has to start with "m_b" -1.3.5 string/char attribute has to start with "m_s" -1.3.6 pointer attribute has to start with "m_p" -1.3.7 template attribute has to start with a template name "m_map" -1.3.8 otherwise "m_" - -2. Type -------- -2.1 every type has to end with "_t" -2.2 types created from templates has to start with a template name -2.3 words in a type has to be separated with "_" - -3. Statement ------------- -3.1 "if", "while" and "for" has to have {} every time. -3.2 { is on the new line every time - -4. Example ----------- - -typedef std::map<int, int> map_new_type_t; - -class CAwesomeClass -{ - private: - map_new_type_t m_NewType; - std::string m_sName; - COtherClass* m_pOtherClass; - void PrivateFunction(int pParameter); - public: - CAwesomeClass(std::string pName) : - m_sName(pName), m_pOtherClass(NULL) - {} -}; - -void CAwesomeClass::PrivateFunction(int pParameter) -{ - if (pParameter != "") - { - // do something - } - else - { - // do something else - } -} diff --git a/doc/DESIGN b/doc/DESIGN deleted file mode 100644 index 6074457..0000000 --- a/doc/DESIGN +++ /dev/null @@ -1,147 +0,0 @@ - Design goals - -We want to catch kernel oopses, binary program crashes (coredumps) -and interpreted languages crashes (Python exceptions, maybe more -in the future). - -We want to support the following use cases: - -* Home/office user with minimal administration - -In this scenario, user expects that abrt will work "out of the box" -with minimal configuration. It will be sufficient if crashes -just show a GUI notification, and user can invoke a GUI tool -to process the crash and report it to bugzilla etc. - -The configuration (like bugzilla address, username, password) -needs to be done via GUI dialogs from the same GUI tool. - -* Standalone server - -The server is installed by an admin. It may lack GUI. -Admin is willing to do somewhat more complex configuration. -Crashes should be recorded, and either processed at once -or reported to the admin by email etc. Admin may log in -and manually request crash(es) to be processed and reported, -using GUI or CLI tools. - -* Mission critical servers, server farms etc. - -Admins are expected to be competent and willing to set up complex -configurations. They might want to avoid any complex crash processing -on the servers - for example, it does not make much sense and/or -can be considered insecure to download debuginfo packages -to such servers. Admins may want to send "raw" crash dumps -to a dedicated server(s) for processing (backtrace, etc). - - - Design - -Abrt design should be flexible enough to accomodate all -of the above usage scenarios. - -The description below is not what abrt does now. -It is (currently incomplete) design notes on how we want -it to achieve design goals. - -Since currently we do not know how to dump oops on demand, -we can only poll for it. There is a small daemon which polls -kernel message buffer and dumps oopses when it sees them. -The dump is written into /var/spool/abrt/DIR. -After this, daemon spawns "abrt-process -d /var/spool/abrt/DIR" -which processes it according to configuration in /etc/abrt/*.conf. - -In order to catch binary crashes, we install a handler for it -in /proc/sys/kernel/core_pattern (by setting it to -"|/usr/libexec/abrt-hook-ccpp /var/spool/abrt %p %s %u"). -When process dumps core, the dump is written into /var/spool/abrt/DIR. -After this, abrt-hook-ccpp spawns "abrt-process -d /var/spool/abrt/DIR" -and terminates. - -When python program crashes, it invokes internel python subroutine -which dumps crash info into ~/abrt/spool/DIR. -[this is a tentative plan, currently we dump in /var/spool/abrt/DIR] -After this, it spawns "abrt-process -d ~/abrt/spool/DIR" -and terminates. - -[Problem: dumping to /var/spool/abrt/DIR needs world-writable -/var/spool/abrt and allows user to go way over his -disk quota. Dumping to ~/abrt/spool/DIR makes it difficult -to present a list of all crashes which happened on the machine - -for example, root-owned processes cannot even access user data -in ~user/* if /home is on NFS4... -] - -When user (admin) wants to see the list of dumped crashes and -process them, he runs abrt-gui or abrt-cli. These programs -perform a dbus call to "com.redhat.abrt" on a system dbus. -If there is no program with this name on it, dbus autostart -will invoke "abrt-process", which registers "com.redhat.abrt" -and processes the call(s). - -abrt-process will terminate after a timeout (a few minutes) -if no new dbus calls are arriving to it. - -The key dbus calls served by abrt-process are: - -- GetCrashInfos(): returns a vector_map_crash_data_t (vector_map_vector_string_t) - of crashes for given uid - v[N]["executable"/"uid"/"kernel"/"backtrace"][N] = "contents" -[see above the problem with producing this list] -- CreateReport(UUID): starts creating a report for /var/spool/abrt/DIR with this UUID. - Returns job id (uint64). - After it returns, when report creation thread has finished, - JobDone(client_dbus_ID,UUID) dbus signal is emitted. - [Problem: how to do privilegged plugin specific actions?] - Solution: if plugin needs an access to some root only accessible dir then - abrt should be run by root anyway - - debuginfo gets installed using pk-debuginfo-install, which cares about - privileges itself, so no problem here -- GetJobResult(UUID): returns map_crash_data_t (map_vector_string_t) -- Report(map_crash_data_t (map_vector_string_t)): - "Please report this crash": calls Report() of all registered reporter plugins - Returns report_status_t (map_vector_string_t) - the status of each call -- DeleteDebugDump(UUID): delete corresponding /var/spool/abrt/DIR. Returns bool - - - Development plan - -Since current code does not match the planned design, we need to gradually -change the code to "morph" it into the desired shape. - -Done: - -* Make abrtd dbus startable. -* Add -t TIMEOUT_SEC option to abrtd. {done} -* Make abrt-gui start abrtd on demand, so that abrt-gui can be started - even if abrtd does not run at the moment. (doesn't work in some cases!) - -Planned steps: - -* make kerneloops plugin into separate daemon (convert it to a hook - and get rid of "cron plugins" which are wrong idea since the begining) - - and make it to the service (write an initscript) -* make C/C++ hook to be started by init script - - init scritp would run ccpp-hook --init whic shoudl just set the core_pattern, which is now done by the C analyzer plugin -* hooks will start the daemon on-demand using dbus - - this is something I'm not sure if it's good idea, but dbus is becoming - to be "un-installable" on Fedora, it's probably ok -* simplify abrt.conf: - - move all plugin related info to plugins/<plugin>.conf - - enabled, action association, etc ... - - make abrtd to parse plugins/*.conf and set the config options - that it understand - - this will fix the case when this is in abrt.conf - - [Cron] - KerneloopsScanner = 120 - - because this should be in plugins/kerneloops.conf - and thus shouldn't exist if kerneloops-addon is - not installed -* ??? -* ??? -* ??? -* ??? -* ??? -* Take over the world diff --git a/doc/HOW_TO_TEST b/doc/HOW_TO_TEST deleted file mode 100644 index 425a2b3..0000000 --- a/doc/HOW_TO_TEST +++ /dev/null @@ -1,41 +0,0 @@ -How to test before releasing new update: - -I. Build and install -=================== -a) build the packages as scratch in koji -b) download and install (the best is to create a local repo and try to install it using yum) -c) create a repository and try to update from previous packages -d) start the daemon and check logs for any sign of a problem -e) try to update from previous Fedora version using created repository - -II. Crash detection -===================== - == 1. Default crash detection == - a) kill some C/C++ app with kill -9 and watch if it's detected by abrt - b) edit some packaged python script to raise an exception and watch is abrt - detects it - c) use our saved kerneloopses and test detection of oopses - - == 2. Advanced crash detection == - a) crash some app that comes from unsigned package - abrt should ignore it - b) disable the gpg check and try repeat step a) - abrt shouldn't ignore it - -- try to add some crash-time action and test if it works - -III. Reporting -============= - == 1. Reporting to bugzilla == - a) try to report some crash to bz using gui - - gui should ask for login+pass - - crash should be reported after filling the right credentials - b) try to report using gui without gnome-keyring - - gui should ask for login+pass - - crash should be reported after filling the right credentials - - login+pass won't be saved - c) try to report every supported crash abrt detects C/C++, oops, python script - d) try to report some crash with bad backtrace - this should fail - e) repeat this with cli - -- test reporting with all reporters plugins like: ticketuploader, filetransport, etc.. - repeating the step 'a' to 'e' - diff --git a/doc/IMPLEMENTATION b/doc/IMPLEMENTATION deleted file mode 100644 index 72f12c7..0000000 --- a/doc/IMPLEMENTATION +++ /dev/null @@ -1,89 +0,0 @@ -Implementation: - -C/C++ handling: -============== - -we change /proc/sys/kernel/core_pattern to invoke abrtd helper to save -the coredump of crashing app: -* helper source code: http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob_plain;f=src/Hooks... -the code responsible for this: - - #define CORE_PATTERN "|/usr/libexec/abrt-hook-ccpp" "/var/spool/abrt" %p %s %u" - ofstream fOutCorePattern; - fOutCorePattern.open(CORE_PATTERN_IFACE); - if (fOutCorePattern.is_open()) - { - fOutCorePattern << CORE_PATTERN << endl; - fOutCorePattern.close(); - } - -%p - pid -%s - signal -%u - uid - -when some crash occurs abrt-hook-ccpp is invoked to store the coredump and some other info -read from /proc/<pid>/: - -executable: - char buf[sizeof("/proc/%u/exe") + sizeof(int)*3]; - sprintf(buf, "/proc/%u/exe", (int)pid); - readlink(buf); - -cmdline: - char path[sizeof("/proc/%u/cmdline") + sizeof(int)*3]; - sprintf(path, "/proc/%u/cmdline", (int)pid); - -both is saved to file in /var/spool/abrt/ccpp-<time>-<pid> readable -only by owner the crashed process: - int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0666); - if(fd){ - do { - n = write(fd, buf, count); - } while (n < 0 && errno == EINTR); - } - -when the hook is done it signalize the daemon (be removing the lock file) and -daemon process the written info and saves some aditional information: - analyzer : name of the plugin used to analyze the crash (ccpp, python) - component : source package name - description : package description (will be removed soon) - kernel : kernel version - release : Fedora release string - uid : uid of the owner of the crashed app - architecture : architecture (i386, x86_64,etc) - package : package name - reason : e.g "Process was terminated by signal 11 (Segmentation fault)" - time : unix time of the crash - -2. send dbus signal (broadcast) about new crash, this signal contains two informations: - 1. uid of the app owner - 2. package name - -This is all what happens when some app crashes, the next step is to process -the coredump and extract the backtrace. This is done on user demand by calling -getReport(UUID) method or automatically if admin sets it in /etc/abrt/abrt.conf -* UUID is unique id of the crash in the database, every user is allowed to see only - his own crashes or kerneloops crashes -- see http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob;f=lib/Plugins/SQL... line 394 - for more details - -1. processing coredump: - a) determine if the crashed binary belongs to some installed package - if it does then: - b) daemon tries to install the debuginfo issuing this command: - -execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs, NULL); - -abrt-debuginfo-install is a shell script using elfutils to get build-ids from coredump and the use -"yum provides" and "yumdownloader" to determine and download the missing debuginfo packages -* script source code: http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob_plain;f=src/Daemo... - c) run gdb and get backtrace from coredump: - see http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob_plain;f=lib/Plugi... line 260 - - gdb is run with the same privileges as the crashed app (setregid, setreuid) - d) BT is saved to same directory where the coredump is - -Once the backtrace is processed all data from the /var/spool/abrt/ccpp-<time>-<pid> is sent -over dbus to the client and then user can edit the backtrace. When user is happy about -the report and command the client (gui, tui) to send the it, the client sends the data back -to the daemon calling the Report(data) method over the dbus. The actual reporting is done by -the respective plugin which is loaded in daemon. diff --git a/doc/INTERPRETED_LANGUAGES b/doc/INTERPRETED_LANGUAGES deleted file mode 100644 index e79a132..0000000 --- a/doc/INTERPRETED_LANGUAGES +++ /dev/null @@ -1,113 +0,0 @@ -This document describes the interaction between ABRT and interpreted -languages. - -Interpreted language is a programming language where the programs -written in that language are not translated into the machine code of -the computer it is on, but interpreted by another software program -known as an interpreter. - -In order to handle interpreted language correctly, ABRT needs a hook -in the language's interpreter. The hook catches serious application -misbehaviors (such as uncaught exceptions, invalid bytecode, missing -library) inside the interpreter and reports the misbehaviors to -ABRT. Hook is usually responsible for assembling the backtrace. - -Another issue are the crashes of the interpreter, which are catched by -the CCpp plugin. When the support for specific interpreter is missing -all these crashes are reported to the interpreter component when -submitting the crash using Bugzilla plugin, regardless of application -executed by the interpreter. To change this, the interpreter should be -handled in src/Daemon/MiddleWare.cpp (see how it is done for Python). - -ABRT currently support only CPython interpreter (the mainstream Python -implementation). Perl, Java, Ruby, and Mono interpreter hooks are yet -to be written. It might be necessary to modify ABRT to support a new -interpreter (patches welcomed). - -Communication between ABRT and hooks -==================================== - -Hook might be a binary plugin plugged to the interpreter, or it might -be interpreted by the interpreter in the same way as the applications -When some event which should be catched by ABRT occurs and is detected -by the hook, the hook reports it to ABRT using ABRT daemon's socket -file. ABRT then creates a new directory describing the crash in -/var/spool/abrt. - -The ABRT's CCpp plugin does not use the socket file, but it creates -crash data directory in /var/spool/abrt directly. Interpreted hooks -must not report crashes this way, because SELinux blocks interpreter -access to /var/spool/abrt and this access can not be granted due to -security issues. - -ABRT socket file resides in /var/run/abrt.socket. Hooks should open -this socket for writing, write the event information, and close the -socket. If the hook leaves the socket opened for a long time without -writing anything, the ABRT daemon which listens on the other side will -close the connection. The maximum number of concurrently opened socket -sessions is also limited. - -The event data are sent to the socket in a number of fields in format -"FIELDNAME=VALUE\0". Various fields impose various restrictions on the -format of VALUE, but generally the VALUE might contain all characters -except \0. Hook sends "DONE\0" after the last field to finish the -entry creation process in the daemon. All fields are mandatory. Field -order does not matter. - -Fields -====== - -PID -Process id of the running interpreter. - -EXECUTABLE -The file with the main entry point of the application. Might be a JAR -archive, a script file, a bytecode file, or the interpreter. It should -be a real file on the filesystem, so ABRT can check the origin of the -file (source package). If the file is not known, the most appropriate -is to shortly describe the reason why it is not known in the field. -However, exceptions raised from interactive shell (a common reason -for unknown file) are hardly useful and should not be reported. - -ANALYZER -The name of an analyzer plugin which should be run during the -analysis. It is used to choose appropriate method of post processing -for the crash dump. Sensible names are "python", "perl", "java" etc. - -BASENAME -Short string indicating the origin of the event. It is used as a part -of directory name: /var/spool/abrt/BASENAME-suffix. Use "python" for -Python exceptions, "ruby" for ruby interpreter, "java" for JRE. - -REASON -A short, one line string describing the event. For Python it is -something like "CCMainWindow.py:1:<module>:ZeroDivisionError: integer -division or modulo by zero". - -BACKTRACE -The backtrace at the moment of the crash, if it is available. May -include other useful information. For example, for ccpp crashes, it -includes register dump. The backtrace should be in a format that is -commonly used by the interpreter. - -Here is an example of a crash report from Python, as it is written to -the socket: -PID=563\0 -EXECUTABLE=/usr/bin/python\0 -ANALYZER=Python\0 -BASENAME=pyhook\0 -REASON=CReporterAssistant.py:415:on_plugin_toggled:ValueError: list.remove(x): -x not in list\0 -BACKTRACE=Traceback (most recent call last): - File "/usr/share/abrt/CReporterAssistant.py", line 415, in on_plugin_toggled - self.selected_reporters.remove(reporter) -ValueError: list.remove(x): x not in list - -Local variables in innermost frame: -complete: False -reporter: <ABRTPlugin.PluginInfo instance at 0x7fc7fb389050> -self: <CReporterAssistant.ReporterAssistant instance at 0x7fc7fdc7acb0> -plugin: <gtk.CheckButton object at 0x7fc7fdc8c9b0 (GtkCheckButton at 0x11d7ed0)> -plugins: [<gtk.CheckButton object at 0x7fc7fdc8c9b0 (GtkCheckButton at 0x11d7ed0)>] -page: <gtk.VBox object at 0x7fc7fdc8c460 (GtkVBox at 0x12f03b0)>\0 -DONE\0 diff --git a/doc/PLUGINS-HOWTO b/doc/PLUGINS-HOWTO deleted file mode 100644 index 81090f3..0000000 --- a/doc/PLUGINS-HOWTO +++ /dev/null @@ -1,155 +0,0 @@ -This document describes how to create your own plugin for abrt. - -Although a base abstract class CPlugin exists, you can't inherit -directly from it. You must use one of the four subclasses, -depending on what you want your plugin to do. - -The subclasses are: - * Action plugin (CAction) - * Analyzer plugin (CAnalyzer) - * Reporter plugin (CReporter) - * Database plugin (CDatabase) - -Each of them requires you to override a different set of methods. - -The pDebugDumpDir parameter is very common: it specifies the directory -that is created to gather information of this specific crash. -The files that were created when the application crashed (such as core dumps) -are all stored here. In addition, the plugins can write -their output files there, if any. - -Plugin types in detail: - - -Analyzer Plugin ---------------- -Crashes differ, depending on where they occur, for example crashes -in the kernel differ from crashes in userspace binaries, which differ -from crashes in python scripts. Therefore, there is a plugin -for each type of application that you want abrt to handle. - -You have to override these methods: - -virtual std::string GetLocalUUID(const char *pDebugDumpPath); -- This method is invoked immediately after crash is detected - and its data is saved by the corresponding hook. - It needs to compute an unique hash (UUID) of the crash. - When a crash occurs and abrt finds an earlier crash with the same - UUID, new crash is discarded as a duplicate, it doesn't show up - in abrt's crash list, but instead a crash count for the earlier - crash is incremented. - -virtual void CreateReport(const char *pDebugDumpDir, int force) -- This method is called when user wants to report a crash - ([Reoprt] button in GUI, etc). Analyzer can perform additional, - more CPU/disk intensive, or interactive processing at this point. - For example, CCpp plugin's CreateReport() processes coredump file, - produces a textual backtrace, and saves it to crash dump directory. - -virtual std::string GetGlobalUUID(const char *pDebugDumpPath); -- This method computes a "duplicate hash" which is used search for - duplicates in remote bug databases such as Bugzilla. They are - "less unique" than LocalUUIDs: ideally, the same crash - on different architecture or with slightly different backtrace - will still have the same GlobalUUID. - [TODO: renaming it to DUPHASH] - - -Action Plugin -------------- -This type of plugin is useful when you need some action to be performed. -Action plugins can be invoked in three ways: - -* Immediately when a crash is encountered (using ActionsAndReporters = ... - directive in abrt.conf). These action plugins are run on every crash - (regardless of crash type). - -* After Analyzer plugin processed a crash (by specifying plugin in - [AnalyzerActionsAndReporters] section, for example: "CCpp = AnActionPlugin"). - In this case, action plugin's Run() method will be run after analyzer - plugin's CreateReport() and GetGlobalUUID() methods have finished. - -* If you need some action to be performed periodically ([Cron] section - in the same file). - -You have to override one method: - -virtual void Run(const char *dir, const char *args); - -The first argument is a directory that contains the current debug -dump, or all debug dumps for periodic actions. -The second argument is a string with arguments (specified in config file). - - -Reporter Plugin ---------------- -This plugin receives the entire finished crash report and -posts/reports it somewhere (e.g. logs it, mails it, posts -it on some web tool...) - -You have to override this method: - -virtual void Report(const map_crash_data_t& pCrashData, - const char *pArgs); -- This method takes the report and presents it somewhere to the world. - The second argument is a string with arguments specified for the reporter. - - -Database Plugin ---------------- -This plugin is used to store the metadata about the crash. The metadata -has to be in a database, to distinguish whether the current crash is or -is not the same as some crash before. The database can be local, or in -some centralized location on the network. - -You have to override these methods: -virtual void Connect(); -virtual void DisConnect(); -- connect and disconnect from the database - -virtual void Insert(const std::string& pUUID, - const std::string& pUID, - const std::string& pDebugDumpPath, - const std::string& pTime); -- insert an entry into the database: you use both UID (user ID) and UUID - (ID of the crash) - -virtual void Delete(const std::string& pUUID, const std::string& pUID); -- delete an entry - -virtual void SetReported(const std::string& pUUID, const std::string& pUID); -- insert information into the database to say that this bug was already - reported (so for example the report plugins won't run several times - for the same bug) - -virtual const vector_database_rows_t GetUIDData(const std::string& pUID); -- get database rows for the specified user ID - -virtual const database_row_t GetUUIDData(const std::string& pUUID, const - std::string& pUID); -- get a database row for the specified user ID and UUID - - -The macro PLUGIN_INFO ---------------------- -Use the macro PLUGIN_INFO in the *.cpp file of your plugin so that your -subclass will be properly registered and treated as a plugin. -This sets up all the lower-level and administrative details to fit your -class into the plugin infrastructure. The syntax is: - -PLUGIN_INFO(type, plugin_class, name, version, description, email, www) -- "type" is one of ANALYZER, ACTION, REPORTER, or DATABASE -- "plugin_class" is the identifier of the class -- "name" is a string with the name of the plugin -- "version" is a string with the version of the plugin -- "description" is a string with the summary of what the plugin does -- "email" and "www" are strings with the contact info for the author - -For example: -PLUGIN_INFO(REPORTER, - CMailx, - "Mailx", - "0.0.1", - "Sends an email with a report via mailx command", - "zprikryl@redhat.com", - "https://fedorahosted.org/crash-catcher/wiki"); diff --git a/doc/coding-style b/doc/coding-style new file mode 100644 index 0000000..3a254b7 --- /dev/null +++ b/doc/coding-style @@ -0,0 +1,64 @@ +Coding style used in abrt +================================= + +1. Class +-------- +1.1 Class has to start with 'C' + +1.2 Method +----------- +1.2.1 method starts witch a capital letter +1.2.2 method name can contain only letters +1.2.3 parameter of a method has to start with the letter 'p' + +1.3 Attribute +------------- +1.3.1 non-float attribute has to start with "m_n" +1.3.2 float attribute has to start with "m_f" +1.3.3 double attribute has to start with "m_d" +1.3.4 bool attribute has to start with "m_b" +1.3.5 string/char attribute has to start with "m_s" +1.3.6 pointer attribute has to start with "m_p" +1.3.7 template attribute has to start with a template name "m_map" +1.3.8 otherwise "m_" + +2. Type +------- +2.1 every type has to end with "_t" +2.2 types created from templates has to start with a template name +2.3 words in a type has to be separated with "_" + +3. Statement +------------ +3.1 "if", "while" and "for" has to have {} every time. +3.2 { is on the new line every time + +4. Example +---------- + +typedef std::map<int, int> map_new_type_t; + +class CAwesomeClass +{ + private: + map_new_type_t m_NewType; + std::string m_sName; + COtherClass* m_pOtherClass; + void PrivateFunction(int pParameter); + public: + CAwesomeClass(std::string pName) : + m_sName(pName), m_pOtherClass(NULL) + {} +}; + +void CAwesomeClass::PrivateFunction(int pParameter) +{ + if (pParameter != "") + { + // do something + } + else + { + // do something else + } +} diff --git a/doc/design b/doc/design new file mode 100644 index 0000000..6074457 --- /dev/null +++ b/doc/design @@ -0,0 +1,147 @@ + Design goals + +We want to catch kernel oopses, binary program crashes (coredumps) +and interpreted languages crashes (Python exceptions, maybe more +in the future). + +We want to support the following use cases: + +* Home/office user with minimal administration + +In this scenario, user expects that abrt will work "out of the box" +with minimal configuration. It will be sufficient if crashes +just show a GUI notification, and user can invoke a GUI tool +to process the crash and report it to bugzilla etc. + +The configuration (like bugzilla address, username, password) +needs to be done via GUI dialogs from the same GUI tool. + +* Standalone server + +The server is installed by an admin. It may lack GUI. +Admin is willing to do somewhat more complex configuration. +Crashes should be recorded, and either processed at once +or reported to the admin by email etc. Admin may log in +and manually request crash(es) to be processed and reported, +using GUI or CLI tools. + +* Mission critical servers, server farms etc. + +Admins are expected to be competent and willing to set up complex +configurations. They might want to avoid any complex crash processing +on the servers - for example, it does not make much sense and/or +can be considered insecure to download debuginfo packages +to such servers. Admins may want to send "raw" crash dumps +to a dedicated server(s) for processing (backtrace, etc). + + + Design + +Abrt design should be flexible enough to accomodate all +of the above usage scenarios. + +The description below is not what abrt does now. +It is (currently incomplete) design notes on how we want +it to achieve design goals. + +Since currently we do not know how to dump oops on demand, +we can only poll for it. There is a small daemon which polls +kernel message buffer and dumps oopses when it sees them. +The dump is written into /var/spool/abrt/DIR. +After this, daemon spawns "abrt-process -d /var/spool/abrt/DIR" +which processes it according to configuration in /etc/abrt/*.conf. + +In order to catch binary crashes, we install a handler for it +in /proc/sys/kernel/core_pattern (by setting it to +"|/usr/libexec/abrt-hook-ccpp /var/spool/abrt %p %s %u"). +When process dumps core, the dump is written into /var/spool/abrt/DIR. +After this, abrt-hook-ccpp spawns "abrt-process -d /var/spool/abrt/DIR" +and terminates. + +When python program crashes, it invokes internel python subroutine +which dumps crash info into ~/abrt/spool/DIR. +[this is a tentative plan, currently we dump in /var/spool/abrt/DIR] +After this, it spawns "abrt-process -d ~/abrt/spool/DIR" +and terminates. + +[Problem: dumping to /var/spool/abrt/DIR needs world-writable +/var/spool/abrt and allows user to go way over his +disk quota. Dumping to ~/abrt/spool/DIR makes it difficult +to present a list of all crashes which happened on the machine - +for example, root-owned processes cannot even access user data +in ~user/* if /home is on NFS4... +] + +When user (admin) wants to see the list of dumped crashes and +process them, he runs abrt-gui or abrt-cli. These programs +perform a dbus call to "com.redhat.abrt" on a system dbus. +If there is no program with this name on it, dbus autostart +will invoke "abrt-process", which registers "com.redhat.abrt" +and processes the call(s). + +abrt-process will terminate after a timeout (a few minutes) +if no new dbus calls are arriving to it. + +The key dbus calls served by abrt-process are: + +- GetCrashInfos(): returns a vector_map_crash_data_t (vector_map_vector_string_t) + of crashes for given uid + v[N]["executable"/"uid"/"kernel"/"backtrace"][N] = "contents" +[see above the problem with producing this list] +- CreateReport(UUID): starts creating a report for /var/spool/abrt/DIR with this UUID. + Returns job id (uint64). + After it returns, when report creation thread has finished, + JobDone(client_dbus_ID,UUID) dbus signal is emitted. + [Problem: how to do privilegged plugin specific actions?] + Solution: if plugin needs an access to some root only accessible dir then + abrt should be run by root anyway + - debuginfo gets installed using pk-debuginfo-install, which cares about + privileges itself, so no problem here +- GetJobResult(UUID): returns map_crash_data_t (map_vector_string_t) +- Report(map_crash_data_t (map_vector_string_t)): + "Please report this crash": calls Report() of all registered reporter plugins + Returns report_status_t (map_vector_string_t) - the status of each call +- DeleteDebugDump(UUID): delete corresponding /var/spool/abrt/DIR. Returns bool + + + Development plan + +Since current code does not match the planned design, we need to gradually +change the code to "morph" it into the desired shape. + +Done: + +* Make abrtd dbus startable. +* Add -t TIMEOUT_SEC option to abrtd. {done} +* Make abrt-gui start abrtd on demand, so that abrt-gui can be started + even if abrtd does not run at the moment. (doesn't work in some cases!) + +Planned steps: + +* make kerneloops plugin into separate daemon (convert it to a hook + and get rid of "cron plugins" which are wrong idea since the begining) + - and make it to the service (write an initscript) +* make C/C++ hook to be started by init script + - init scritp would run ccpp-hook --init whic shoudl just set the core_pattern, which is now done by the C analyzer plugin +* hooks will start the daemon on-demand using dbus + - this is something I'm not sure if it's good idea, but dbus is becoming + to be "un-installable" on Fedora, it's probably ok +* simplify abrt.conf: + - move all plugin related info to plugins/<plugin>.conf + - enabled, action association, etc ... + - make abrtd to parse plugins/*.conf and set the config options + that it understand + - this will fix the case when this is in abrt.conf + + [Cron] + KerneloopsScanner = 120 + + because this should be in plugins/kerneloops.conf + and thus shouldn't exist if kerneloops-addon is + not installed +* ??? +* ??? +* ??? +* ??? +* ??? +* Take over the world diff --git a/doc/how-to-test b/doc/how-to-test new file mode 100644 index 0000000..425a2b3 --- /dev/null +++ b/doc/how-to-test @@ -0,0 +1,41 @@ +How to test before releasing new update: + +I. Build and install +=================== +a) build the packages as scratch in koji +b) download and install (the best is to create a local repo and try to install it using yum) +c) create a repository and try to update from previous packages +d) start the daemon and check logs for any sign of a problem +e) try to update from previous Fedora version using created repository + +II. Crash detection +===================== + == 1. Default crash detection == + a) kill some C/C++ app with kill -9 and watch if it's detected by abrt + b) edit some packaged python script to raise an exception and watch is abrt + detects it + c) use our saved kerneloopses and test detection of oopses + + == 2. Advanced crash detection == + a) crash some app that comes from unsigned package - abrt should ignore it + b) disable the gpg check and try repeat step a) - abrt shouldn't ignore it + +- try to add some crash-time action and test if it works + +III. Reporting +============= + == 1. Reporting to bugzilla == + a) try to report some crash to bz using gui + - gui should ask for login+pass + - crash should be reported after filling the right credentials + b) try to report using gui without gnome-keyring + - gui should ask for login+pass + - crash should be reported after filling the right credentials + - login+pass won't be saved + c) try to report every supported crash abrt detects C/C++, oops, python script + d) try to report some crash with bad backtrace - this should fail + e) repeat this with cli + +- test reporting with all reporters plugins like: ticketuploader, filetransport, etc.. + repeating the step 'a' to 'e' + diff --git a/doc/implementation b/doc/implementation new file mode 100644 index 0000000..72f12c7 --- /dev/null +++ b/doc/implementation @@ -0,0 +1,89 @@ +Implementation: + +C/C++ handling: +============== + +we change /proc/sys/kernel/core_pattern to invoke abrtd helper to save +the coredump of crashing app: +* helper source code: http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob_plain;f=src/Hooks... +the code responsible for this: + + #define CORE_PATTERN "|/usr/libexec/abrt-hook-ccpp" "/var/spool/abrt" %p %s %u" + ofstream fOutCorePattern; + fOutCorePattern.open(CORE_PATTERN_IFACE); + if (fOutCorePattern.is_open()) + { + fOutCorePattern << CORE_PATTERN << endl; + fOutCorePattern.close(); + } + +%p - pid +%s - signal +%u - uid + +when some crash occurs abrt-hook-ccpp is invoked to store the coredump and some other info +read from /proc/<pid>/: + +executable: + char buf[sizeof("/proc/%u/exe") + sizeof(int)*3]; + sprintf(buf, "/proc/%u/exe", (int)pid); + readlink(buf); + +cmdline: + char path[sizeof("/proc/%u/cmdline") + sizeof(int)*3]; + sprintf(path, "/proc/%u/cmdline", (int)pid); + +both is saved to file in /var/spool/abrt/ccpp-<time>-<pid> readable +only by owner the crashed process: + int fd = open(pPath, O_WRONLY | O_TRUNC | O_CREAT, 0666); + if(fd){ + do { + n = write(fd, buf, count); + } while (n < 0 && errno == EINTR); + } + +when the hook is done it signalize the daemon (be removing the lock file) and +daemon process the written info and saves some aditional information: + analyzer : name of the plugin used to analyze the crash (ccpp, python) + component : source package name + description : package description (will be removed soon) + kernel : kernel version + release : Fedora release string + uid : uid of the owner of the crashed app + architecture : architecture (i386, x86_64,etc) + package : package name + reason : e.g "Process was terminated by signal 11 (Segmentation fault)" + time : unix time of the crash + +2. send dbus signal (broadcast) about new crash, this signal contains two informations: + 1. uid of the app owner + 2. package name + +This is all what happens when some app crashes, the next step is to process +the coredump and extract the backtrace. This is done on user demand by calling +getReport(UUID) method or automatically if admin sets it in /etc/abrt/abrt.conf +* UUID is unique id of the crash in the database, every user is allowed to see only + his own crashes or kerneloops crashes +- see http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob;f=lib/Plugins/SQL... line 394 + for more details + +1. processing coredump: + a) determine if the crashed binary belongs to some installed package + if it does then: + b) daemon tries to install the debuginfo issuing this command: + +execlp("abrt-debuginfo-install", "abrt-debuginfo-install", coredump, tempdir, debuginfo_dirs, NULL); + +abrt-debuginfo-install is a shell script using elfutils to get build-ids from coredump and the use +"yum provides" and "yumdownloader" to determine and download the missing debuginfo packages +* script source code: http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob_plain;f=src/Daemo... + c) run gdb and get backtrace from coredump: + see http://git.fedorahosted.org/git/abrt.git?p=abrt.git;a=blob_plain;f=lib/Plugi... line 260 + - gdb is run with the same privileges as the crashed app (setregid, setreuid) + d) BT is saved to same directory where the coredump is + +Once the backtrace is processed all data from the /var/spool/abrt/ccpp-<time>-<pid> is sent +over dbus to the client and then user can edit the backtrace. When user is happy about +the report and command the client (gui, tui) to send the it, the client sends the data back +to the daemon calling the Report(data) method over the dbus. The actual reporting is done by +the respective plugin which is loaded in daemon. diff --git a/doc/interpreted-languages b/doc/interpreted-languages new file mode 100644 index 0000000..e79a132 --- /dev/null +++ b/doc/interpreted-languages @@ -0,0 +1,113 @@ +This document describes the interaction between ABRT and interpreted +languages. + +Interpreted language is a programming language where the programs +written in that language are not translated into the machine code of +the computer it is on, but interpreted by another software program +known as an interpreter. + +In order to handle interpreted language correctly, ABRT needs a hook +in the language's interpreter. The hook catches serious application +misbehaviors (such as uncaught exceptions, invalid bytecode, missing +library) inside the interpreter and reports the misbehaviors to +ABRT. Hook is usually responsible for assembling the backtrace. + +Another issue are the crashes of the interpreter, which are catched by +the CCpp plugin. When the support for specific interpreter is missing +all these crashes are reported to the interpreter component when +submitting the crash using Bugzilla plugin, regardless of application +executed by the interpreter. To change this, the interpreter should be +handled in src/Daemon/MiddleWare.cpp (see how it is done for Python). + +ABRT currently support only CPython interpreter (the mainstream Python +implementation). Perl, Java, Ruby, and Mono interpreter hooks are yet +to be written. It might be necessary to modify ABRT to support a new +interpreter (patches welcomed). + +Communication between ABRT and hooks +==================================== + +Hook might be a binary plugin plugged to the interpreter, or it might +be interpreted by the interpreter in the same way as the applications +When some event which should be catched by ABRT occurs and is detected +by the hook, the hook reports it to ABRT using ABRT daemon's socket +file. ABRT then creates a new directory describing the crash in +/var/spool/abrt. + +The ABRT's CCpp plugin does not use the socket file, but it creates +crash data directory in /var/spool/abrt directly. Interpreted hooks +must not report crashes this way, because SELinux blocks interpreter +access to /var/spool/abrt and this access can not be granted due to +security issues. + +ABRT socket file resides in /var/run/abrt.socket. Hooks should open +this socket for writing, write the event information, and close the +socket. If the hook leaves the socket opened for a long time without +writing anything, the ABRT daemon which listens on the other side will +close the connection. The maximum number of concurrently opened socket +sessions is also limited. + +The event data are sent to the socket in a number of fields in format +"FIELDNAME=VALUE\0". Various fields impose various restrictions on the +format of VALUE, but generally the VALUE might contain all characters +except \0. Hook sends "DONE\0" after the last field to finish the +entry creation process in the daemon. All fields are mandatory. Field +order does not matter. + +Fields +====== + +PID +Process id of the running interpreter. + +EXECUTABLE +The file with the main entry point of the application. Might be a JAR +archive, a script file, a bytecode file, or the interpreter. It should +be a real file on the filesystem, so ABRT can check the origin of the +file (source package). If the file is not known, the most appropriate +is to shortly describe the reason why it is not known in the field. +However, exceptions raised from interactive shell (a common reason +for unknown file) are hardly useful and should not be reported. + +ANALYZER +The name of an analyzer plugin which should be run during the +analysis. It is used to choose appropriate method of post processing +for the crash dump. Sensible names are "python", "perl", "java" etc. + +BASENAME +Short string indicating the origin of the event. It is used as a part +of directory name: /var/spool/abrt/BASENAME-suffix. Use "python" for +Python exceptions, "ruby" for ruby interpreter, "java" for JRE. + +REASON +A short, one line string describing the event. For Python it is +something like "CCMainWindow.py:1:<module>:ZeroDivisionError: integer +division or modulo by zero". + +BACKTRACE +The backtrace at the moment of the crash, if it is available. May +include other useful information. For example, for ccpp crashes, it +includes register dump. The backtrace should be in a format that is +commonly used by the interpreter. + +Here is an example of a crash report from Python, as it is written to +the socket: +PID=563\0 +EXECUTABLE=/usr/bin/python\0 +ANALYZER=Python\0 +BASENAME=pyhook\0 +REASON=CReporterAssistant.py:415:on_plugin_toggled:ValueError: list.remove(x): +x not in list\0 +BACKTRACE=Traceback (most recent call last): + File "/usr/share/abrt/CReporterAssistant.py", line 415, in on_plugin_toggled + self.selected_reporters.remove(reporter) +ValueError: list.remove(x): x not in list + +Local variables in innermost frame: +complete: False +reporter: <ABRTPlugin.PluginInfo instance at 0x7fc7fb389050> +self: <CReporterAssistant.ReporterAssistant instance at 0x7fc7fdc7acb0> +plugin: <gtk.CheckButton object at 0x7fc7fdc8c9b0 (GtkCheckButton at 0x11d7ed0)> +plugins: [<gtk.CheckButton object at 0x7fc7fdc8c9b0 (GtkCheckButton at 0x11d7ed0)>] +page: <gtk.VBox object at 0x7fc7fdc8c460 (GtkVBox at 0x12f03b0)>\0 +DONE\0 diff --git a/doc/plugins-howto b/doc/plugins-howto new file mode 100644 index 0000000..81090f3 --- /dev/null +++ b/doc/plugins-howto @@ -0,0 +1,155 @@ +This document describes how to create your own plugin for abrt. + +Although a base abstract class CPlugin exists, you can't inherit +directly from it. You must use one of the four subclasses, +depending on what you want your plugin to do. + +The subclasses are: + * Action plugin (CAction) + * Analyzer plugin (CAnalyzer) + * Reporter plugin (CReporter) + * Database plugin (CDatabase) + +Each of them requires you to override a different set of methods. + +The pDebugDumpDir parameter is very common: it specifies the directory +that is created to gather information of this specific crash. +The files that were created when the application crashed (such as core dumps) +are all stored here. In addition, the plugins can write +their output files there, if any. + +Plugin types in detail: + + +Analyzer Plugin +--------------- +Crashes differ, depending on where they occur, for example crashes +in the kernel differ from crashes in userspace binaries, which differ +from crashes in python scripts. Therefore, there is a plugin +for each type of application that you want abrt to handle. + +You have to override these methods: + +virtual std::string GetLocalUUID(const char *pDebugDumpPath); +- This method is invoked immediately after crash is detected + and its data is saved by the corresponding hook. + It needs to compute an unique hash (UUID) of the crash. + When a crash occurs and abrt finds an earlier crash with the same + UUID, new crash is discarded as a duplicate, it doesn't show up + in abrt's crash list, but instead a crash count for the earlier + crash is incremented. + +virtual void CreateReport(const char *pDebugDumpDir, int force) +- This method is called when user wants to report a crash + ([Reoprt] button in GUI, etc). Analyzer can perform additional, + more CPU/disk intensive, or interactive processing at this point. + For example, CCpp plugin's CreateReport() processes coredump file, + produces a textual backtrace, and saves it to crash dump directory. + +virtual std::string GetGlobalUUID(const char *pDebugDumpPath); +- This method computes a "duplicate hash" which is used search for + duplicates in remote bug databases such as Bugzilla. They are + "less unique" than LocalUUIDs: ideally, the same crash + on different architecture or with slightly different backtrace + will still have the same GlobalUUID. + [TODO: renaming it to DUPHASH] + + +Action Plugin +------------- +This type of plugin is useful when you need some action to be performed. +Action plugins can be invoked in three ways: + +* Immediately when a crash is encountered (using ActionsAndReporters = ... + directive in abrt.conf). These action plugins are run on every crash + (regardless of crash type). + +* After Analyzer plugin processed a crash (by specifying plugin in + [AnalyzerActionsAndReporters] section, for example: "CCpp = AnActionPlugin"). + In this case, action plugin's Run() method will be run after analyzer + plugin's CreateReport() and GetGlobalUUID() methods have finished. + +* If you need some action to be performed periodically ([Cron] section + in the same file). + +You have to override one method: + +virtual void Run(const char *dir, const char *args); + +The first argument is a directory that contains the current debug +dump, or all debug dumps for periodic actions. +The second argument is a string with arguments (specified in config file). + + +Reporter Plugin +--------------- +This plugin receives the entire finished crash report and +posts/reports it somewhere (e.g. logs it, mails it, posts +it on some web tool...) + +You have to override this method: + +virtual void Report(const map_crash_data_t& pCrashData, + const char *pArgs); +- This method takes the report and presents it somewhere to the world. + The second argument is a string with arguments specified for the reporter. + + +Database Plugin +--------------- +This plugin is used to store the metadata about the crash. The metadata +has to be in a database, to distinguish whether the current crash is or +is not the same as some crash before. The database can be local, or in +some centralized location on the network. + +You have to override these methods: +virtual void Connect(); +virtual void DisConnect(); +- connect and disconnect from the database + +virtual void Insert(const std::string& pUUID, + const std::string& pUID, + const std::string& pDebugDumpPath, + const std::string& pTime); +- insert an entry into the database: you use both UID (user ID) and UUID + (ID of the crash) + +virtual void Delete(const std::string& pUUID, const std::string& pUID); +- delete an entry + +virtual void SetReported(const std::string& pUUID, const std::string& pUID); +- insert information into the database to say that this bug was already + reported (so for example the report plugins won't run several times + for the same bug) + +virtual const vector_database_rows_t GetUIDData(const std::string& pUID); +- get database rows for the specified user ID + +virtual const database_row_t GetUUIDData(const std::string& pUUID, const + std::string& pUID); +- get a database row for the specified user ID and UUID + + +The macro PLUGIN_INFO +--------------------- +Use the macro PLUGIN_INFO in the *.cpp file of your plugin so that your +subclass will be properly registered and treated as a plugin. +This sets up all the lower-level and administrative details to fit your +class into the plugin infrastructure. The syntax is: + +PLUGIN_INFO(type, plugin_class, name, version, description, email, www) +- "type" is one of ANALYZER, ACTION, REPORTER, or DATABASE +- "plugin_class" is the identifier of the class +- "name" is a string with the name of the plugin +- "version" is a string with the version of the plugin +- "description" is a string with the summary of what the plugin does +- "email" and "www" are strings with the contact info for the author + +For example: +PLUGIN_INFO(REPORTER, + CMailx, + "Mailx", + "0.0.1", + "Sends an email with a report via mailx command", + "zprikryl@redhat.com", + "https://fedorahosted.org/crash-catcher/wiki");