aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2020-linuxdays/makefile10
-rw-r--r--2020-linuxdays/pres.pdfbin0 -> 78631 bytes
-rw-r--r--2020-linuxdays/pres.tex379
3 files changed, 389 insertions, 0 deletions
diff --git a/2020-linuxdays/makefile b/2020-linuxdays/makefile
new file mode 100644
index 0000000..a90bd93
--- /dev/null
+++ b/2020-linuxdays/makefile
@@ -0,0 +1,10 @@
+FILE=pres
+
+$(FILE).pdf: $(FILE).tex $(patsubst %.svg,%.pdf,$(wildcard *.svg))
+ lualatex -shell-escape $<
+
+%.pdf: %.svg
+ inkscape -D -z --file=$< --export-pdf=$@ --export-latex
+
+clean:
+ ls | grep -v -E "($(FILE).tex|makefile|scheme|svg|png|jpg|eps)$$" | xargs rm -rf
diff --git a/2020-linuxdays/pres.pdf b/2020-linuxdays/pres.pdf
new file mode 100644
index 0000000..33e08d6
--- /dev/null
+++ b/2020-linuxdays/pres.pdf
Binary files differ
diff --git a/2020-linuxdays/pres.tex b/2020-linuxdays/pres.tex
new file mode 100644
index 0000000..288b5e1
--- /dev/null
+++ b/2020-linuxdays/pres.tex
@@ -0,0 +1,379 @@
+\documentclass[aspectratio=169]{beamer}
+\usetheme{metropolis}
+\usepackage{lmodern}
+\usepackage[czech]{babel}
+\usepackage[utf8]{inputenc}
+\usepackage{graphicx}
+\usepackage{emoji}
+\setemojifont{Quivira}
+\usepackage{wrapfig}
+\usepackage{color}
+\usepackage{mathtools}
+\usepackage{hyperref}
+\usepackage{epstopdf}
+\usepackage{amsmath}
+\usepackage{minted}
+\hypersetup{
+ colorlinks,
+ citecolor=black,
+ filecolor=black,
+ linkcolor=black,
+ urlcolor=black
+}
+\usepackage{pdflscape}
+
+\title{Proradná obsluha chyb \emoji{dagger}}
+\author{Kar(t)el Kočí}
+\date{3.10.2020}
+
+\begin{document}
+
+\frame{\titlepage}
+
+\begin{frame}[fragile]
+ \frametitle{Kdo za ty chyby může?}
+ \only<2>{\huge \textbf{Uživatel!}}
+ \only<3>{\footnotesize Programátor..}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co si pod chybami programátor představí?}
+ \begin{itemize}
+ \item \textbf{Nečekaný stav dat}
+ \item Nečekaný běh aplikace (špatný algoritmus)
+ \item Nečekané ukončení aplikace (segfault, ..)
+ \item Nečekaný obsah souboru či čtení ze soketu
+ \item Nečekaný obsah sdílené paměti
+ \item \textbf{Nečekaná návratová hodnota}
+ \item Nečekaný stav souborů (chybějící složka atd.)
+ \item Nečekaná odezva od periferie či soketu
+ \item A další \ldots
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co si pod chybami představí uživatel?}
+ \Large Nefunguje to!
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Teď vážně, požadavky}
+ \begin{columns}
+ \column{.45\textwidth}
+ Uživatel:
+ \begin{itemize}
+ \item Nechce, aby program spadl
+ \item Když už spadne, tak chce vědět jak to opravit
+ \item Když už neřekneme jak opravit, tak chce vědět proč
+ \item Nechce více informací než dokáže vstřebat
+ \end{itemize}
+ \column{.45\textwidth}
+ Programátor:
+ \begin{itemize}
+ \item To někdy není možné a je to jediné východisko
+ \item Programátor nemůže pokrýt každou situaci
+ \item To nemusí být ani v moci programu
+ \item Potřebuje trace, například aby dohledal jak se to stalo
+ \end{itemize}
+ \end{columns}
+ Programátor není Bůh, ale měl by být a měl by se snažit uživatelům práci s
+ jeho stvořením zpříjemnit.
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co s chybou když nastane?}
+ Záleží na tom o jakou chybu se jedná.
+ \begin{itemize}
+ \item Fatální chyby
+ \begin{itemize}
+ \item Pády (\textit{segfault, invalid instruction, \ldots})
+ \item Nečekané stavy (\textit{tady ještě před chvílí byl soubor \ldots})
+ \item Bezvýchodné stavy (\textit{tady měl být soubor se vstupem \dots})
+ \end{itemize}
+ \item Řešitelné chyby
+ \begin{itemize}
+ \item Krajní (\textit{soubor vytvořil někdo jiný \ldots})
+ \item Očekávané (\textit{soubor se nezdařilo vytvořit, protože chybí složka, vytvoříme složku \dots})
+ \item Ignorované (\textit{unlink souboru selhal, protože neexistuje \dots})
+ \end{itemize}
+ \end{itemize}
+
+ A taky záleží, jestli jsme knihovna nebo program!
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co když nastane pád?}
+
+ \begin{columns}
+ \column{.50\textwidth}
+ \centerline{\textbf{Program}}
+ Pokud se nesnaží, tak se ani o tom nedozví.
+ \column{.50\textwidth}
+ \centerline{\textbf{Knihovna}}
+ Ani se o tom nedozví a většinou by se neměla ani snažit.
+ \end{columns}
+
+ \vspace{1cm}
+
+ \begin{minted}[frame=lines]{c}
+struct foo *foo = NULL;
+foo->fee = 0;
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co když nastane nečekaný stav?}
+ \begin{columns}
+ \column{.50\textwidth}
+ \centerline{\textbf{Program}}
+ Ukončení programu a výpis stavových informací
+ \begin{minted}[frame=lines]{python}
+file = open(path, "w")
+file.close()
+file = open(path)
+# raises: FileNotFoundError
+ \end{minted}
+ \begin{minted}[frame=lines]{c}
+fclose(file);
+file = fopen(path, "r");
+assert(file);
+ \end{minted}
+ \column{.50\textwidth}
+ \centerline{\textbf{Knihovna}}
+ Necháme vyřešit aplikaci. Nikdy ne \texttt{exit} a vyvarujte se
+ \texttt{abort}.
+ \begin{minted}[frame=lines]{c}
+fclose(file);
+file = fopen(path, "r");
+if (file == NULL) {
+ liberrno = LIB_ERR_LOST_FILE;
+ return false;
+}
+ \end{minted}
+ \end{columns}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Odbočka k C a knihovnám: Jak hlásit error?}
+ \begin{itemize}
+ \item Návratová hodnota funkce
+ \begin{minted}[frame=lines]{c}
+enum {
+ FOO_ERR_FOO,
+} foo() { return FOO_ERR_FOO; }
+ \end{minted}
+ \item Proměnná s chybou
+ \begin{minted}[frame=lines]{c}
+enum liberror {
+ LIB_ERR_FOO,
+};
+thread_local enum liberror liberrno;
+ \end{minted}
+ \item Výjimka (s nějakou knihovnou, která je implementuje)
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co když nastane bezvýchodný stav?}
+ \begin{columns}
+ \column{.50\textwidth}
+ \centerline{\textbf{Program}}
+ Ukončení programu.
+ \begin{minted}[frame=lines]{python}
+try:
+ file = open(sys.argv[1])
+except FileNotFoundError:
+ logger.critical("Input missing: %s",
+ sys.argv[1])
+except PermissionError:
+ logger.critical(
+ "Input unaccessible: %s",
+ sys.argv[1])
+ \end{minted}
+ \column{.50\textwidth}
+ \centerline{\textbf{Knihovna}}
+ Necháme vyřešit aplikaci.
+ \begin{minted}[frame=lines]{python}
+def handle_args(argv):
+ """
+ :raises FileNotFoundError:
+ First argument wasn't valid path
+ :raises PermissionError:
+ First is unaccessible path
+ """
+ file = open(argv[1])
+ \end{minted}
+ \end{columns}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Odbočka k ukončovacím rutinám: Jak ukončit program?}
+ Je nutné uvolnit každou dosažitelnou paměť?
+
+ Rozdělme si zdroje vůči procesu:\\
+
+ \begin{columns}
+ \column{.50\textwidth}
+ Interní
+ \begin{itemize}
+ \item Alokovaná paměť
+ \item Otevřené file descriptory (soubory, sockety, atd.)
+ \item Namapovaná paměť
+ \end{itemize}
+ \column{.50\textwidth}
+ Externí
+ \begin{itemize}
+ \item Data buffery s výstupem na disk (ne \texttt{fclose} ale \texttt{fflush})
+ \item Dočasné soubory dosažitelné na file-systému
+ \end{itemize}
+ \end{columns}
+
+ \vspace{0.4cm}
+
+ Dělejme jen to, co musíme. Zbytek za nás udělá kernel a jazyk.
+
+ Interní za nás udělá někdo jiný, my se musíme starat pouze o externí.
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Ještě větší odbočka k C \texttt{exit}}
+ \url{https://www.gnu.org/software/libc/manual/html_node/Termination-Internals.html}
+
+ \begin{minted}[frame=lines]{c}
+typedef void (*onexit_t)(void *arg);
+struct onexit { onexit_t func; void *arg; struct onexit *next; };
+struct onexit *onexit = NULL;
+void onexit_handler() {
+ for (; onexit; onexit = onexit->next)
+ onexit->func(onexit->arg);
+}
+
+atexit(onexit_handler);
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co když nastane řešitelná chyba?}
+ \begin{columns}
+ \column{.50\textwidth}
+ \centerline{\textbf{Program}}
+ Tak ji prostě vyřešíme, nebo ještě lépe ji předejdeme.
+ \begin{minted}[frame=lines]{python}
+pathlib.Path("foo").mkdir(
+ parents=True, exist_ok=True)
+file = open("foo/fee", "w")
+ \end{minted}
+ \column{.50\textwidth}
+ \centerline{\textbf{Knihovna}}
+ Tak ji vyřešíme. Lepší je ale nechat vybrat aplikaci, jestli se má
+ automaticky řešit nebo vrátit raději error.
+ \begin{minted}[frame=lines]{python}
+def open(self, path, mkdir=True):
+ if mkdir:
+ pathlib.Path(path).parent.mkdir(
+ parent=True, exist_ok=True)
+ file = open(path, "w")
+ \end{minted}
+ \end{columns}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Závěrem: jde to i přehnat}
+ \begin{minted}[frame=lines]{c}
+int fd = open(path, O_RDONLY);
+char buf[BUFSIZ];
+while (true) {
+ if (read(fd, buf, BUFSIZ) == -1) {
+ switch (errno) {
+ case EWOULDBLOCK:
+ case EAGAIN:
+ continue;
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \Large Error: unable to exit, user is not informed!
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Nahlášení chyby}
+ Před tím než chybu ošetříme, musíme ji nahlásit!
+
+ V pořadí od vývojářsky po uživatelsky přivětivé:
+ \begin{itemize}
+ \item Memory dump
+ \item Stack trace
+ \item Popis chyby se zdrojem chyby (zdrojový soubor, funkce, řádka, \dots)
+ \item Popis chyby
+ \item Popis chyby a návrh řešení
+ \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co kdy zvolit ale?}
+ \begin{description}
+ \item[Memory dump] jen pro pády a většinou zajistí systém
+ \item[Stack trace] jen pro nečekané stavy a na vyžádání
+ \item[Zdroj chyby] jen jako méně invazivní alternativa ke stacktrace
+ \item[Popis] vždy
+ \item[Návrh řešení] vždy pokud je možné
+ \end{description}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Co v popisu říci uživateli, aby jim i nám to k něčemu bylo?}
+ \begin{enumerate}
+ \item Popis by měl být pokud možno unikátní pro každou chybu.
+ \item Poskytnout výpis relevantních dat (cesta k souboru a pod.).
+ \item Nevypisujte nerelevantní data!
+ \item Popis by měl být výstižný a přesný.
+ \end{enumerate}
+
+ Ujistěte se, že data která vypisujete jsou validní!
+ \begin{verbatim}
+Called uri_path on URI of scheme: https
+ \end{verbatim}
+ \begin{minted}[frame=lines]{diff}
+-error("URI download failed (" .. u:path() .. "): " .. u:download_error())
++error("Getting URI (" .. u:uri() .. ") failed: " .. u:download_error())
+ \end{minted}
+\end{frame}
+
+\begin{frame}[fragile]
+ \frametitle{Kdy hlásit chybu?}
+ \textbf{Vždy!}
+
+ Hlašte chyby ve více úrovních:
+ \begin{description}
+ \item[CRITICAL] pro nečekané a bezvýchodné stavy (následuje ukončení
+ programu)
+ \item[ERROR] pro krajní řešitelné chyby
+ \item[WARNING] pro krajní řešitelné chyby
+ \item[NOTICE] žádné chyby
+ \item[INFO] pro očekávané chyby
+ \item[DEBUG] pro ignorované chyby
+ \end{description}
+\end{frame}
+
+
+\begin{frame}[fragile]
+ \frametitle{Checklist závěrem}
+ \begin{enumerate}
+ \item Zamyslete se, co za data od volání získáte, a jak moc datům ke
+ kterým přistupujete můžete věřit
+ \item Chyby které nám mohou nastat rozřadíme
+ \item Při detekci chyby oznámíme uživateli
+ \item Vyřešíme chybu dle toho o jaký typ se jedná
+ \end{enumerate}
+\end{frame}
+
+
+\begin{frame}
+ \Large \textbf{Fatal error: no more slides \emoji{cry}}
+
+ \Large Děkuji za pozornost.
+
+ \url{git.cynerd.cz}
+\end{frame}
+
+\end{document}