War stories. Part 2
by Sergey Lyubka, Cesanta CTO, for Dublin C/C++ User Group
Broken downloads
- A problem was reported that the HTTP sever does not serve certain files correctly
- Debugging in a browser revelead that the Content-Length header was too large
#if defined(__MINGW32__)
typedef struct stat cs_stat_t;
#else
typedef struct _stati64 cs_stat_t;
#endif
int mg_stat(const char *path, cs_stat_t *st) {
....
return _wstati64(wpath, (struct _stati64 *) st);
}
...
mg_printf(conn, "Content-Length: %Iu\r\n", st->st_size);
Broken downloads
- Bottom line: fixed next day
- Unit test added
- Disappointed users
A hilarious debugging session
- Two terminals
- First is used to edit the code in vim
- Second is used to compile & run
- Typical printf - debugging
- Server segfaults on fragmented websocket frame
$ make clean all COPTS="-O0 -g" && ./srv
...
Staring on port 7021
...
Segmentation fault: 11
static int deliver(struct mg_connection *c) {
...
if (!is_first_fragment(p[0])) {
// defragmentation code ...
....
}
...
}
Terminal 1
Terminal 2
A hilarious debugging session
- Okay let's put some useful printfs into the defragmentation code
$ make clean all COPTS="-O0 -g" && ./srv
...
Staring on port 7021
...
Segmentation fault: 11
static int deliver(struct mg_connection *c) {
...
if (!is_first_fragment(p[0])) {
printf("boyz, tornado is coming\n"); // <--
// defragmentation code ...
....
}
...
}
Terminal 1
Terminal 2
- Recompiled and run - a message does not appear though
A hilarious debugging session
- Okay moved the printf to the function start
$ make clean all COPTS="-O0 -g" && ./srv
...
Staring on port 7021
...
Segmentation fault: 11
static int deliver(struct mg_connection *c) {
printf("boyz, tornado is coming\n"); // <--
...
if (!is_first_fragment(p[0])) {
....
}
...
}
Terminal 1
Terminal 2
- No change ...
A hilarious debugging session
- Moved printf to main()
$ make clean all COPTS="-O0 -g" && ./srv
...
Staring on port 7021
...
Segmentation fault: 11
int main(int argc, const char *argv[]) {
printf("boyz, tornado is coming\n"); // <--
...
}
Terminal 1
Terminal 2
- No change !!
- WTF?
A hilarious debugging session
- Bottom line: about 2 hours wasted
- Disassembling revealed no signs of printf
- Suspected filesystem to not saving a file
- Suspected compiler to not to recompile
- Suspected nihilists to hack vim
A weird compilation error
static void ev_handler(struct mg_connection *c,
int ev,
void *ev_data) {
...
c->flags |= WEB_TTY;
...
}
Before:
After:
static void ev_handler(struct mg_connection *c,
int ev,
void *ev_data) {
...
c->flags |= WEB_TTY;
...
printf("%p connected\n", c); // <-- Added
...
}
error: format specifies type 'void *' but the argument
has type '<dependent type>' [-Werror,-Wformat]
testutil.c:19:32: error: use of undeclared identifier 'c'
printf("%p connected\n", c);
^
Results in compilation error:
A weird compilation error
- Bottom line: about 20 minutes wasted
- Renaming a variable helped
- Hexdump revealed the reason
Thank you!
contact me at
sergey.lyubka@cesanta.com
Copy of War stories. Part 2
By Sergey Lyubka
Copy of War stories. Part 2
This presentation goes over notable and sometimes funny software engineering experiences from the past
- 937