diff --git a/config.toml b/config.toml
index a4b1250..e6fba20 100644
--- a/config.toml
+++ b/config.toml
@@ -6,3 +6,6 @@ summaryLength = 20
[markup.goldmark.renderer]
unsafe=true
+
+[markup.highlight]
+ style="vim"
diff --git a/content/posts/gdb-multiprocessing.md b/content/posts/gdb-multiprocessing.md
new file mode 100644
index 0000000..33b6505
--- /dev/null
+++ b/content/posts/gdb-multiprocessing.md
@@ -0,0 +1,171 @@
+---
+title: "Debugging multiprocessing software with GDB"
+date: 2024-09-28T14:33:17+02:00
+---
+
+## backstory
+
+Since ever I started the development of my high school finals project - [a proxy library](http://git.0xdeadbeer.xyz/0xdeadbeer/proxlib) -
+I have had the desire to master the art of debugging multiprocessing software.
+Up until now I had no idea it was even possible due to the scarse general
+information available about it.
+
+`set follow-fork-mode [mode]` seemed promising and quite honestly, worked as expected.
+Except, I realized that to debug my proxy, I was in need of a more dynamic approach such as:
+ - being asked whether to follow the child/parent as I catch multiple forks
+ - switching between the parent or multiple children instantly
+ - releasing the parent while I only debug the child or vice versa
+
+I read more about it online and it seemed as if the first of my requirements was an already supported feature
+of GDB - (`set follow-fork-mode ask`) - which would ask the user at runtime whether they want to follow
+the child or the parent the second they hit a fork/vfork syscall. Sadly, newer versions of GDB have had it cut off
+and deprecated for whatever reason.
+
+The frustration got me really close to taking initiative and writing myself a little patch for the modern versions of GDB
+so they would also have this useful feature. But something told me there had to be a better way. And oh boy, better way there was.
+
+## start
+
+{{< highlight c "linenos=inline" >}}
+/* main.c */
+
+#include
+#include
+
+int main(void) {
+ fprintf(stdout, "--multiprocessing example--\n");
+ for (int i = 0; i < 5; i++) {
+ pid_t pid = fork();
+ if (pid == 0) {
+ fprintf(stdout, ">>hello from child: %d\n", i);
+ return 0;
+ }
+ if (pid < 0) {
+ fprintf(stderr, ">>failed forking\n");
+ return -1;
+ }
+ }
+
+ fprintf(stdout, ">>hello from parent\n");
+
+ return 0;
+}
+{{< / highlight >}}
+
+We are going to step through this program - getting into the nitty griddy of debugging and seeing
+what options we have depending on our demands. First of all, use your compiler of choice. I am going to use
+GCC and turn on debugging info.
+
+ gcc -g3 main.c -o main
+
+Before we continue, make sure you at least have the following setting enabled in .gdbinit:
+
+ set detach-on-fork off
+
+A very convenient option that will block execution of both the parent and the new child - not
+letting one of them run unless you manually call continue.
+
+## following the parent
+
+This scenario is unsurprisingly simple. GDB does this automatically, therefore, I will not cover it.
+
+{{}}
+[hemisquare@detached-hemi tmp]$ gdb main
+(gdb) break main
+Breakpoint 1 at 0x1161: file main.c, line 7.
+(gdb) run
+Starting program: /home/hemisquare/tmp/main
+[Thread debugging using libthread_db enabled]
+Using host libthread_db library "/usr/lib/libthread_db.so.1".
+
+Breakpoint 1, main () at main.c:7
+7 fprintf(stdout, "--multiprocessing example--\n");
+(gdb) s
+--multiprocessing example--
+8 for (int i = 0; i < 5; i++) {
+(gdb)
+9 pid_t pid = fork();
+(gdb)
+[New inferior 2 (process 51915)]
+[Thread debugging using libthread_db enabled]
+Using host libthread_db library "/usr/lib/libthread_db.so.1".
+10 if (pid == 0) {
+(gdb) p pid
+$1 = 51915
+(gdb) # we are the parent
+{{}}
+
+## following the child
+
+Similar to the parent example, I will step until we hit the first fork syscall.
+
+{{}}
+[hemisquare@detached-hemi tmp]$ gdb main
+(gdb) break main
+Breakpoint 1 at 0x1161: file main.c, line 7.
+(gdb) run
+Starting program: /home/hemisquare/tmp/main
+[Thread debugging using libthread_db enabled]
+Using host libthread_db library "/usr/lib/libthread_db.so.1".
+
+Breakpoint 1, main () at main.c:7
+7 fprintf(stdout, "--multiprocessing example--\n");
+(gdb) s
+--multiprocessing example--
+8 for (int i = 0; i < 5; i++) {
+(gdb)
+9 pid_t pid = fork();
+(gdb)
+[New inferior 2 (process 52175)]
+[Thread debugging using libthread_db enabled]
+Using host libthread_db library "/usr/lib/libthread_db.so.1".
+10 if (pid == 0) {
+(gdb)
+{{}}
+
+So, currently we are inside the parent "inferior". And inferior is just a GDB term for processes, threads, or whatever it is that you are debugging.
+Through forks, we create another inferior which we can switch to. As you can see, we now have two inferiors:
+
+{{}}
+(gdb) info inferiors
+ Num Description Connection Executable
+* 1 process 52172 1 (native) /home/hemisquare/tmp/main
+ 2 process 52175 1 (native) /home/hemisquare/tmp/main
+(gdb)
+{{}}
+
+The '*' indicates the inferior we are currently residing in. Inferior 2 is the newborn child we just forked.
+Let's switch into the child!
+
+{{}}
+(gdb) inferior 2
+[Switching to inferior 2 [process 52175] (/home/hemisquare/tmp/main)]
+[Switching to thread 2.1 (Thread 0x7ffff7dab740 (LWP 52175))]
+#0 0x00007ffff7e90b57 in _Fork () from /usr/lib/libc.so.6
+(gdb) finish
+Run till exit from #0 0x00007ffff7e90b57 in _Fork () from /usr/lib/libc.so.6
+0x00007ffff7e966e2 in fork () from /usr/lib/libc.so.6
+(gdb) finish
+Run till exit from #0 0x00007ffff7e966e2 in fork () from /usr/lib/libc.so.6
+0x0000555555555192 in main () at main.c:9
+9 pid_t pid = fork();
+(gdb) nexti
+10 if (pid == 0) {
+(gdb) p pid
+$1 = 0
+(gdb) s
+11 fprintf(stdout, ">>hello from child: %d\n", i);
+(gdb)
+>>hello from child: 0
+12 return 0;
+(gdb)
+{{}}
+
+As you can see, here, we were able to step through the code of the child. Notice that the parent is still handing where we
+left it at. It is totally okay to now switch back into the parent inferior and continue the execution from there.
+
+## conclusion
+
+Knowing this is essential for debugging my proxy library. I am thankful I now know GDB just a little better and was
+hopefully able to provide you with a useful learning resource. I might extend this article in case I master more
+interesting multiprocessing or multithreading techniques.
diff --git a/themes/minth/assets/css/main.css b/themes/minth/assets/css/main.css
index 9bd4766..ac7ef63 100644
--- a/themes/minth/assets/css/main.css
+++ b/themes/minth/assets/css/main.css
@@ -11,10 +11,9 @@ body {
/*background: linear-gradient(0deg, rgba(0,78,255,1) 0%, rgba(0,0,0,1) 100%);
*/
background-image: url('../hacker-manifesto-bg.jpg');
- background-repeat: repeat;*/
+ background-repeat: repeat;
/*background-size: contain;
background-attachment: fixed;*/
- margin: 0;
}
@media only screen and (min-width: 800px) {
diff --git a/themes/minth/static/css/global.css b/themes/minth/static/css/global.css
index 529f407..ebf8d48 100644
--- a/themes/minth/static/css/global.css
+++ b/themes/minth/static/css/global.css
@@ -11,6 +11,11 @@
color: white;
}
+pre code {
+ display: block;
+ background: black;
+}
+
.post-title {
font-size: 200px;
}
@@ -86,3 +91,9 @@ code {
img {
width: 100%;
}
+
+.code {
+ background: #ffffff !important;
+ color: black !important;
+}
+