Monthly Archives: January 2016

KDevelop: Debuggen von Programmen, die root-Rechte benötigen

Häufig arbeite ich mit KDevelop und dort auch gern mit dem integrierten Debugger bzw. dem entsprechenden Frontend für gdb. Heute hatte ich ein Programm am Wickel, was einen lauschenden Socket auf einem privilegierten Port aufmachen will. Mit KDevelop konnte ich dies nicht direkt mit den nötigen Root-Rechten starten. Um es trotzdem debuggen zu können, kann man stattdessen mit gdbserver und remote debugging arbeiten. Das geht so:

In der bereits angelegten Launch Configuration geht man auf die Einstellungen für Debug und dort kann man unter »Remote Debugging« drei Dateien angeben. Man muss hier tatsächlich zwei bis drei Dateien anlegen und diese mit dem passenden Inhalt füllen. Die erste ist das gdb config script, wo man nochmal den Pfad zum ausgeführten Binary einträgt. Das sollte genau das sein, was auch über das Projekt kompiliert wird (mit Debug-Symbolen drin natürlich):

file /home/adahl/Work/build/tlue-gcc/src/tlue

Das dritte ist das run gdb script, hier sagt man dem gdb wohin er sich verbinden soll, in diesem Fall wird das ein gdbserver sein, der auf der selben Maschine auf Port 12345 lauschen wird:

target remote localhost:12345

Jetzt ist noch die Frage, was kommt bei run shell script rein? Wenn man es leer lässt, muss man den gdbserver von Hand starten, bevor man in KDevelop auf »Debug« klickt, das könnte auf einer entsprechenden Konsole in dem Build-Ordner des Programms so aussehen:

sudo gdbserver localhost:12345 ./src/tlue

Oder man baut sich noch eine dritte Datei, diesmal ein Shell-Skript, wo man den zuletzt genannten Befehl ausführt. Dieses gibt man dann an zweiter Stelle an. Klappte hier bei mir spontan nicht, weil sudo da noch nach einem Passwort fragt, was ich in KDevelop nicht eingeben kann.

Java Enterprise Loop

Following a discussion in the Netz39 IRC channel I created a short Java Enterprise Loop for those in need.

package com.penguineering.seriousnonsense;

/*
 * Short usage instructions:
 *
 * 		final Runnable loopee = ... // Acquire some runnable instance
 * 		EnterpriseLoop.forRunnable(loopee).run();
 *
 * or put it in a thread:
 * 
 * 		new Thread(EnterpriseLoop.forRunnable(loopee)).start();
 *
 *
 * Whatever kills your design best.
 */

public class EnterpriseLoop implements Runnable {
	public static EnterpriseLoop forRunnable(final Runnable _loopee) throws NullPointerException {
		return new EnterpriseLoop(_loopee);
	}
	
	private final Runnable loopee;
	
	private EnterpriseLoop(final Runnable _loopee) throws NullPointerException {
		if (_loopee == null)
			throw new NullPointerException("Runnable _loopee must not be null!");
		
		this.loopee = _loopee;
	}
	
	public Runnable getLoopee() {
		return loopee;
	}
	
	@Override
	public void run() {
		while (true)
			try {
				loopee.run();
			} catch {Throwable t) {
				// ignore
			}
	}
}

To adhere to development standards usually found in situations leading to the need of an enterprise loop, I neither documented the code (except for a short usage instruction to save you from thinking about those lines you are going to copy) nor tested it.

I leave this to the public domain to successfully serve as a bad example.