October 28, 2008

Multiplatform debugging environment, Part 2 (Linux)

Remote debugging for Linux

There is no port of Visual Studio Remote Debugger for Linux, so we cannot use the same technology as for Windows. Let’s think what we have on Linux. Yes, GDB. But gdb needs source code and symbol table to do all the debug stuff.

One solution is to use gdbserver on debug machine and connect to this server using gdb from computer with source codes (Windows XP). As far as I know VS does not work with gdb, so if we want to use GDB GUI, we need to install Netbeans or Eclipse on Windows. I don’t like this solution.

Another, better solution is to mount windows shared folder with source codes, symbol table, executable file and so on.

First of all, you need to create shared folder.

If you do not have a special “guest” user, please create one and choose a password for him.



Now we need to simulate the same folder structure on the Linux computer as on the source one. This is done for the gdb to be able to find both source code and symbol tables. For example, assume that the project directory with source code is G:\Source and the path to the executable is G:\Source\project\exe\lx\debug\english\schedmgr.exe.

First of all, mount the windows shared folder

sudo mkdir /mnt/G:
sudo mkdir /mnt/G:/Source
sudo mount –t cifs –o username=guest_user,password=guest_password //dev-gburanov/Source /mnt/G:/Source

It is better to add automatic mounting on logon. To do this, add the following line to etc/fstab.

//deb-gburanov/Source /mnt/G:/Source cifs auto,username=user,password=guest_password 0 0

Now we need to set the correct paths to the gdb. To do this, we can use gdb configuration file .gdbinit. Create the file (if it is not created yet) in your home folder (i.e. /home/gburanov). Add two lines to the file:

dir /mnt
path /mnt
Now when the gdb will start searching for G:\Source\our_project.cpp on the linux machine, it will try to add /mnt at the beginning of the path (now it will be /mnt/G:/source/our_project.cpp), and as soon as we mounted the share, this is correct path.
That’s all we need for the gdb debugger. Now we can use it to debug solution in terminal.

About GUI. Now, when you have done gdb configuration, you can use any GUI you want. I prefer NetBeans. There is one hint about Netbeans – it does not understand “:” symbol , so I create another one directory for executables only.

ln -s /mnt/G\:/Source/project/exe/lx/ /home/gburanov/NetBeansProjects/executables/
Now all you need to do is to create new empty project, add the executable file as Linker Output (in our case /home/gburanov/NetBeansProjects/executables/lx/debug/English/test_time_conversions.exe, remove Build First checkbox, put breakpoints and… done.


October 24, 2008

Multiplatform debugging environment, Part 1 (Windows)

Introduction

Our product is compiled on many OSes, including Windows, Linux and Mac OsX. I have two work computers to do all the work. Our source control is CVS, and I have WinCVS installed (you can also use TortoiseCVS as well). These are just my preferences; any guy in the team (if he is rather experienced developer) can use any tool he wants to do the job. I said experienced, because there is recommended list of the developer tools, and there is something like official support for the problems with this tools. Anyway, there are guys on the project who use notepad to write code, command line to build project and gdb to debug it.

As I said, I have two work computers. Main computer is running Windows XP with Visual Studio 2005. It also has Virtual machine (I prefer VMware, there are guys who prefer Parallels, at least the Parallels developers work in the same building =)). The VMware is needed to run test environment. Generally, we have a rule: develop machine is for code writing and building only. If you want to run the code, use virtual machine (even if you want to run it on the same environment as development). Most of Acronis products do use low-level disk operations, so every bug in program can cause corrupting of developing environment.

Second computer is Mac OS. Actually, is it not mine only, we have one for the whole team. It is iMac (computer + monitor in the same brick), so anyone can easily move it from one seat to another. We use real computer, because Mac OS on VMware runs completely slowly.

All code (both for Linux, Mac Os and Windows) is compiled on the main computer using make files. For Linux and Mac Os we use cygwin to compile. But, as I said before, after the compiling you test the code on virtual machine or Mac Os machine.

The way of debugging differs for different operation systems.

Remote debugging for Windows

For windows I use remote debugging tools (included with the VS 2005 or VS 2003). You need to install debugging monitor (just copy one folder) to the environment, where you program will be tested. First of all, disable authentication.

Now the monitor starts listening to connections
Switch back to main computer and load VS. Load your solution, and then open project properties.

Chose “Remote Windows Debugger”, type in remote server name and choose correct connection type (Remove with no authentication). In “Remote command” field type in the patch to the executed file on remote computer. That’s all! Your solution is ready for remote debugging.

October 20, 2008

DST issues

The first bug I got in new team - time issues when switching from DST to non-DST time. I found this bug simply by showing the calendar for half a year. The calendar looked really fine, but there were two October, 25 in it. I looked at the code that increments the day

byte SchedulerTime::IncDay(int dayCount /* = 1 */)
{

LinearTicks() += TicksPerDay * dayCount;
FillComponent();
return
GetDay();
}

The code looked fine at the first glance. The internal data structure for CommonTime is number of milliseconds since January (on Windows, different value on Mac, Linux). What’s wrong with 25 October? Correct answer – in Russia this day is switching day from DST to non-DST time. And yes, the 25 October is the special day that lasts 25, not 24 hours.

How should we fix that bug? We should check the UTC offset. The UTC offsets shows us the difference between UTC time and our local time.For example, for Moscow the offset is +3/+4 depending on DST/non-DST time. The corrected code looks the following:

byte SchedulerTime::IncDay(int dayCount /* = 1 */)
{

uni_time_t previousOffset = GetUtcOffset();
LinearTicks() += TicksPerDay * dayCount;
FillComponent();
FixTimeWhenShiftingUtcOffset(previousOffset);
return
GetDay();
}

The implementation of FixTimeWhenShiftingUtcOffset is:
/**
* @description fixes time when there was a dst/nondst switch during incrementing/decrementing day
* @param previousOffset UTC time offset before the incremention/decremention
*/

void
SchedulerTime::FixTimeWhenShiftingUtcOffset(const uni_time_t& previousOffset)
{

if
(!UseUtc)
{

uni_time_t currentOffset = GetUtcOffset();
if
(currentOffset != previousOffset)
{

LinearTime += currentOffset - previousOffset;
FillComponent();
}
}
}

The next question is: If we schedule task to be executed every day once at 2.30, should the task execute twice during DST to non-DST switch (because we have 2.30 twice) or should it execute once (because the man wanted to execute it every day). What is your answer? Why?