200 likes | 220 Views
Learn good programming and debugging practices, tips for designing and testing your proxy, and a tool for testing your multi-threaded proxy.
E N D
15-213: How to dBug your (threaded) proxy Jiří Šimša PARALLEL DATA LABORATORY Carnegie Mellon University
Motivation http://www.pdl.cmu.edu/ “Concurrency is a good servant but a bad master” • Today we will cover: • good programming practices • good debugging practices • tips for designing and testing your proxy • a tool for testing your multi-threaded proxy
Before We Start http://www.pdl.cmu.edu/ • Go to: http://www.virtualbox.org/ and download and install VirtualBox on your laptop • Go to: http://www.cs.cmu.edu/~213/resources.html and start downloading the dbug-213.vdi
GOOD programming PRACTICES http://www.pdl.cmu.edu/
1. Know Your Library Calls Spending time reading a man page will dispel your misconceptions and save you hours of frustration. http://www.pdl.cmu.edu/ ... pthread_mutex_lock(&mutex); if (cache_empty()) { pthread_mutex_unlock(&mutex); ... } ... pthread_mutex_unlock(&mutex); ...
2. Check Return Values Handling error cases correctly will facilitate identification of program failure root cause. http://www.pdl.cmu.edu/ ... ret = accept(sockfd,addr,addrlen); if (ret == -1) { perror(“Accept failed.\n”); } else { ... } ... assert(pthread_mutex_lock(&mutex) == 0); ...
3. Use Conditional Compilation Spending time including informative messages will greatly improve your debugging efficiency. http://www.pdl.cmu.edu/ void * request_handler(void *args) { #ifdef DEBUG printf(“Entering %s”, __FUNCTION__); #endif ... } $ gcc –DDEBUG ...
4. Learn and Use Makefiles Spending time learning how to use a Makefile will save you hours of repetitive and dull work. http://www.pdl.cmu.edu/ CC = gcc CFLAGS = -g -Wall -Werror LDFLAGS = -lpthread ... all: proxy proxy-test proxy: proxy.ccsapp.c $(CC) -o $@ $(CFLAGS) -O3 $(LDFLAGS) $^ proxy-test: proxy.ccsapp.c $(CC) -o $@ $(CFLAGS) -DDEBUG $(LDFLAGS) $^
5. Keep It Simple (Silly) Start with the simplest approach possible. Often getting the simplest design right will be enough. http://www.pdl.cmu.edu/ ... int main(intargc, char *argv[]) { ... init_proxy(); while(1) { if ((ret = accept(sockfd,addr,addrlen)) > 0) { setup_args(sockfd,addr,addrlen,args); ret = pthread_create(&tid, 0, handler, args); assert(ret == 0); } else { perror(“Accept failed.\n”); } } }
6. Avoid Premature Optimizations Start with the simplest approach possible. Often getting the simplest design right will be enough. http://www.pdl.cmu.edu/ ... // All cache operations take O(1) time. Sick! fancy_cache_t cache; ... inline void lookup_cache_entry(structcache_entry *entry) { ... // 100+ lines of code ... }
7. Learn and Use gdb Learning how to control and inspect execution of a program is instrumental to efficient debugging. http://www.pdl.cmu.edu/ $ ulimit -c unlimited $ ./proxy 1234 Segmentation fault (core dumped) $ gdb ./proxy core ... (gdb) bt ... #3 0x08049865 in doit (fd=4) at proxy.c:179 #4 0x080496c5 in thread_handler (connfdp=0x9920008) at proxy.c:136 #5 0x00da7cc9 in start_thread (arg=0xb78adb70) at pthread_create.c:304 ...
Summary of Good Practices http://www.pdl.cmu.edu/ Know Your Library Calls Check Return Values Use Conditional Compilation Learn and Use a Makefile Keep it Simple Avoid Premature Optimization Learn and Use gdb
Testing Your Proxy http://www.pdl.cmu.edu/
Sequential Proxy Test Case http://www.pdl.cmu.edu/ Open three terminal windows 1:$ cd $TINY; make; sudo ./tiny 80 2:$ cd $PROXY; make; ./proxy 1234 3:$ curl –x localhost:1234 http://localhost <html> <head><title>test</title></head> <body> <img align="middle" src="godzilla.gif"> Dave O'Hallaron </body> </html>
Case Proxy Test Case http://www.pdl.cmu.edu/ Open three terminal windows 1:$ cd $TINY; make; sudo ./tiny 80 2:$ cd $PROXY; make; ./proxy 1234 3:$ curl –x localhost:1234 HTTP://LoCaLhOst <html> <head><title>test</title></head> <body> <img align="middle" src="godzilla.gif"> Dave O'Hallaron </body> </html>
Port Proxy Test Case http://www.pdl.cmu.edu/ Open three terminal windows 1:$ cd $TINY; make; ./tiny 8080 2:$ cd $PROXY; make; ./proxy 1234 3:$ curl –x localhost:1234 http://localhost:8080 <html> <head><title>test</title></head> <body> <img align="middle" src="godzilla.gif"> Dave O'Hallaron </body> </html>
Cache Proxy Test Case http://www.pdl.cmu.edu/ Open three terminal windows 1:$ cd $TINY; make; sudo ./tiny 80 2:$ cd $PROXY; make; ./proxy 1234 3:$ curl –x localhost:1234 http://localhost 3:$ killall -9 tiny 3:$ curl –x localhost:1234 http://localhost <html> <head><title>test</title></head> <body> <img align="middle" src="godzilla.gif"> ...
Concurrent Proxy Test Case http://www.pdl.cmu.edu/ Open three terminal windows 1:$ cd $TINY; make; sudo ./tiny 80 2:$ cd $PROXY; make; ./proxy 1234 3:$ export CMD=“curl –x localhost:1234 http://localhost” 3:$ $CMD & $CMD Which request will get serviced 1st? Will the 2nd request be serviced from cache? Will a non-reentrant function be called concurrently? How to try out all possible cases?
USING DBUG http://www.pdl.cmu.edu/
dBug: Concurrent gdb and more http://www.pdl.cmu.edu/ Systematic Testing of Concurrent Systems Given a concurrent system and a test, dBug systematically explores all possible ways in which the test could have executed dBug searches for deadlocks, data races, and assertion violations