Saturday, January 05, 2019

Renovate an old SSD drive

Some time ago, my friend gave me a second hand SSD, which come from his old laptop. The SSD was kept in good condition. However, the SSD was not being used for more than half year.

I plugged the SSD to my desktop as an additional drive. The BIOS was able to detect the SSD, but it didn't function normally. It took much longer time to boot into my Ubuntu Linux. In the dmesg log, it was showing a lot of IO errors:


Basically, the SSD was unstable and slow. At that time, I thought the SSD was broken.

Then, I tried to dig out more information about SSD on the Internet. According to the article The Truth About SSD Data Retention, SSD is not good for storing data offline for long period of time. The SSD was not being used for more than half year, the data in the SSD may be lost or corrupted. This could corrupt the file system and could screw up the controller of SSD. This may be the reason for the instability and slowness.

I was thinking it may fix the problem, if I wipe out all the data in the SSD. Some articles on the web mentioned that we can restore the SSD performance by secure erase. Then, I issued the secure erase commands suggested in the page to clean up the data in SSD. Luckily, the SSD was refreshed. Now, the SSD is working perfectly.

Key takeaways:

  1. SSD is not good for offline data storing.
  2. If your SSD is unstable or slow, secure erase may be the last resort to fix the problem.


Sunday, September 03, 2017

Games on Linux

One of the major disadvantage of Linux is luck of games. Most of PC games are only run on Windows. However, as a casual game player, I can see there is a lot of improvement in recent years.

First of all, there are more and more games officially support Linux. Steam, a popular game distribution platform, can run on Linux. Steam also maintains a Linux distribution, called SteamOS, which is specialized for using Steam. In Steam, I can search the games supporting Linux. Recently, I have bought two games, Civilization V and Cities: Skyline, from Steam. Both are running smoothly on my Ubuntu box.

If the game only support Windows, there is still a hope that it can run on WINE. WINE is similar to a Windows virtual machine (VM), but it simulates Windows on OS level instead of hardware level. The performance of WINE is much better than traditional VM, especially on 3D graphics. However, WINE is not prefect. The community of WINE is keep improving it. You can get a list of Windows software which can run in WINE here. In my past experience, with some tricks mentioned in the WINE page, I can run Windows version of Steam. In the Steam, I can run AOE II, AOE III, and Simcity 4 Deluxe. Recently, I follow the guide to install League of Legends (LoL). It is also running fine on my Ubuntu box.

Last but not the least, the open source community also developed a lot of open source games for Linux. I found the most impressive one is SuperTuxKart.

Happy gaming on Linux!


Saturday, July 29, 2017

JUnit Test for Singletons/Static Variables

JUnit runs all tests in one instance of JVM. Therefore, it assumes individual test cases are independent and should not interfere each other. However, this is not true for singletons or static variables. The status of singletons and static variables carry over across test cases. This causes troubles for JUnit tests.
Let me show you an example. Assume we have a MyService class: MyService class is a typical implementation of singleton. In addition, it has two methods:
init(String config)
to initialize MyService with a config parameter. This method can only call once.
doSomeService(FileWriter)
ask MyService to do something. In this example, it writes the value of someConfig via FileWriter parameter.
Now, we want to implement some JUnit test classes to verify the implementation. The first test class initializes MyService with "Hello!" and verifies whether doSomeService(...) really tries to write "Hello!". The second test class initializes MyService with "Hi!" and verifies whether doSomeService(...) really tries to write "Hi!". If you run the above test cases one-by-one in your IDE, it works fine. However, if you run both test cases in one go, one of the test cases fails:
As mentioned at the beginning, JUnit tests are run in one instance of JVM. If you run both test cases, because of singleton design pattern, the MyService instance of first test case is carried over to the second test case. When the second test case calls the init(...) method, it throws exception. This is actually one of the infamous disadvantages of singleton design pattern. However, you may not be able to re-design your system. Then, how can we fix the unit tests?

Actually, there is a workaround to force reloading of classes for each test using class loader trick. For each JUnit test class, we use a customized test runner which enforce a separated instance of class loader for each test class. Then, the classes we want to test will be reloaded for each JUnit test class Here is the implementation of the test runner (SeparateClassloaderTestRunner):
To use the SeparateClassloaderTestRunner, you need to replace the "@RunWith(MockitoJUnitRunner.class)" to "@RunWith(SeparateClassloaderTestRunner.class)" in the test classes. Then, if you run both test cases in one go, both test cases will pass.
You can get the demo source code at github - https://github.com/loklam/reloadclassdemo.

Thursday, July 27, 2017

Working Copy - a good Git Client for iPad

Recently, I want to read some source code located in GitHub. I found there is a handy tool - Working Copy. It's a Git Client for iPad. It has a nice code browser and code viewer/editor with syntax highlight. You can even edit the code and commit the changes. Now, I can read code during travelling.

Sunday, May 14, 2017

a lightweight code generator - cog


Recently, I need to write a library to read and write JSON messages for C++. The library should be able to serialize/deserialize an message object to/from a JSON message. However, the messages schema can be changed from time to time for new requirements. So, I need to think a way to adapt the schema change easily.

In Java world, there are many mature JSON libraries support this, e.g. JSON-B, Gson, .... However, C++ doesn't have reflection. We cannot have C++ version of libraries like JSON-B and Gson. For C++, the only option is code generation. There are number of ways to do code generation. After some search on the web, I found a Python based code generator -- Cog, and here is a success story about using Cog. The tool works very good and it's lightweight. With the code generation, it saved me a lot of time when there is any schema change.

Sunday, February 05, 2017

Recovery Ubuntu boot entry in UEFI after upgraded motherboard firmware

Nowadays, UEFI is commonly used to replace the BIOS. UEFI doesn't use boot sector in disks. Instead, UEFI comes with a boot manager. During installation of an OS, e.g. Ubuntu Linux, the OS installer usually setup the boot loader (e.g. GRUB) in EFI partition and update the boot config. The boot config provides information for boot manager to locate the boot loader. The tricky part is the boot config is stored in NVRAM on the motherboard. During firmware upgrade, NVRAM can be reset. This means the boot config will also be reset and lost the boot loader information.
I encountered this issue when I upgrade the firmware of my Xubuntu box. Now, I would like to show you how to recovery the boot config. This demo is using Ubuntu 16.04 on Virtual Box.

  1.  Get an installation CD or a flash drive with installer of Ubuntu 16.04 (You should have it when you install the Ubuntu first time). If you don't have it, get it from here.
  2.  Boot up the system using the CD or flash drive. In GRUB, select "Try Ubuntu without installation"
  3. Then, you should be able to boot into a fresh Ubuntu, like
  4. Open a terminal and run "sudo su" to switch to root user.
  5. Now, we need to know where the EFI partition located. We can use "fdisk -l /dev/xxx" command to list out the paration, like:
    Refer to the above screen, we know that the EFI partition is on the first partition of device "sda" (i.e. /dev/sda1). (Note: the actual location of the EFI partition on your box can be different from this demo.)
  6. Then, we mount the EFI partition to verify if the Ubuntu GRUB loader is installed. To do this, mount the drive using command "udiskctrl mount -b /dev/xxx" and check if the EFI partition contains "EFI/ubuntu/shimx64.efi" file. E.g.:
  7. After the above verification, we have enough information to create the add the boot entry using the command:
    efibootmgr -c -d /dev/xxx -p n -l '\EFI\ubuntu\shimx64.efi'
    where "xxx" is the disk device contains the EFI partition, and "n" is the partition number. E.g.:

  • shutdown the box, remove the CD or flash drive and reboot. Then, we should be able to see the GRUB again.
  • Monday, January 02, 2017

    jq - a powerful unix command line tool for handling JSON data

    Nowadays, JSON is a popular data format, especially in web services domain. However, traditionally, Unix command line tools, e.g. sed, awk, grep, etc., are not capable to handle JSON data format. So, it is hard to write shell scripts to reading JSON data.
    Fortunately, I found a handy and powerful tool - jq. In this page, I want to show you an example of using jq to extract weather forecast in JSON format to CSV. First of all, I get the data from weather forecast serveice of api.openweathermap.org and save it to "forcecast.json" file:
    Here is the raw data, hard to read by human,
    jq can print the JSON in pretty format, with color:
    Now, I show you how to extract the dt_txt(forecast time), temp (forecast temperature) and humidity (forecast humidity) from the JSON data to CSV:
    Just a  single command can covert JSON to CSV. How powerful is it! For the usage details of jq, you can refer to the manual

    Friday, December 23, 2016

    Log TCP Connections to WAN in OpenWrt

    I have a router running OpenWrt 15.05. I would like to log all the TCP connections. To achieve this, I just need to add a line in the firewall custom rule like:
    iptables -A forwarding_lan_rule -p tcp -m state --state NEW -m limit --limit 30/sec -j LOG --log-prefix "NEW Conn "
    
    
    Then, login the router as root, and restart the firewall with the following command:
    /etc/init.d/firewall restart
    

    The following shows how the System Log looks like after enable the custom rule:

    Tuesday, December 20, 2016

    Audio Volume Normalizer

    When I switched from MS Windows to Linux as my primary desktop, I found that I needed to adjust the audio volume frequently. For example, different YouTube videos have different levels of audio volume, but I didn't notice this in MS Windows. With some searching on the web, I found that MS Windows did some tricks behind the scene, called "Loudness Equalization".

    Do we have similar ticks in Linux? After some digging on the web, I found the solution. In the following, I will show you how I do that in my XUbuntu 16.04 LTS box:
    1. First of all, need to install "swh-plugins". Actually, we only need the Compressor Plugin.
      sudo apt-get install swh-plugins
      I am not an expert on Sound Engineering, but I found a page which explained the parameters well.
    2. Next, we need to config PulseAudio to load the plugin and set the "default sink". To do this, create a file at $HOME/.config/pulse/default.pa with below contents:
      #include system-wise config
      .include /etc/pulse/default.pa
      
      #compressor -- for normalize audio volume
      .ifexists module-ladspa-sink.so
      .nofail
      load-module module-ladspa-sink sink_name=ladspa_out plugin=sc1_1425.so label=sc1 control=3,401,-30,4,5,12
      set-default-sink ladspa_out
      .fail
      .endif
      
    3. Then, you just need to kill PulseAudio daemon to restart with the new config:
      pulseaudio -k
    4. If everything goes well, you can run any application with audio playback (e.g. Mpalyer). To confirm the setup, you can run "pavucontrol" command to bring up the "Volume Control" GUI. In the "Volume Control" GUI you should see "SC1" plugin is being used, like:
    References:

    Monday, December 19, 2016

    Install Remix OS on VirtualBox

    Remix OS is an Android OS which can run on PC. Because I want to run some Android Apps in my Ubuntu desktop, I tried to install Remix OS in VirtualBox VM. Here are the steps:
    1. Download the Remix OS (64-bit version) at http://www.jide.com/remixos-for-pc#downloadNow.
    2. Unzip release_Remix_OS_for_PC_Android_M_64bit_B2016112101.zip. We need the file Remix_OS_for_PC_Android_M_64bit_B2016112101.iso, which is a CD image of Remix OS.
    3. Create a new Virtual Machine in VirtualBox like below. Please ensure you select the "Remix_OS_for_PC_Android_M_64bit_B2016112101.iso" disk image for the CD driver of the VM. For Audio, please select "ASLA Audio Driver" and "ICH AC97".
    4. Start the VM, and you will see the GRUB menu. Press "Tab" immediately to edit the boot command.

    5. Append "INSTALL=1" in the boot command and then press "Enter"

    6. Follow the steps to create a new partition:





    7. Choose the newly created partition to install Remix OS
    8. Select "ext4" as the format of the new partition

    9. Choose "Yes" to install GRUB.
    10. Choose "Yes" to install "/system" dir as read-write.
    11. After a few minutes, you will see the installation completed screen. Now, you have to eject the CD of the VM (Device --> Optical Drives --> remove disk from virtual drive). Then, select "Reboot".
    12. If everything goes smooth, you should see the GRUB screen.
    13. After a few minutes you will see the welcome screen. Please note that you need to disable the mouse integration (Input --> Mouse Integration) of the VM, otherwise, you can't use mouse in Remix OS.
    14. Just follow the steps on the screen to initialize the Remix OS. Then, you should see "home" screen. To enable Google Play, you need to double click the "Play activator" and follow the steps on the screen.

    Software versions:
    XUbuntu 16.04.1 LTS
    Linux Kernel 4.4.0-53-generic (64-bit)
    Virtual Box 5.0.24_Ubuntu r108355

    Reference:
    https://gist.github.com/cs8425/7315d86a273e57a988245345df68a4f9


    Saturday, November 26, 2016

    Theory vs Practice -- Linked List and Array

    When I was a student, in algorithm course about data structures, we were comparing arrays and linked lists. Arrays are faster than linked lists on random access (O(1) vs O(n)). However, listed lists are faster than arrays for random insertion/deletion operations (O(1) vs O(n)).

    In reality, when we consider the L1 and L2 cache in a computer system, the above is not always true. Recently, I found a good page comparing the performance of C++ std::vector (dynamic array), std::list (linked list) and std::deque. When the size of an element is small, vectors and deques perform better than lists. It's because the spatial locality. In arrays, elements are packed next to each others in memory, but in lists, elements are located randomly and linked by pointers. Therefore, when iterating the elements in lists, it will have much higher chance of cache missed. In other words, lists can't get the benefit from cache.

    Monday, October 10, 2016

    Setup Another Instance of sshd Support Google's Two-Factor Authentication in Raspberry Pi

    For security reason, I want to enhance the sshd running in my Raspberry Pi to make use of Two-Factor Authentication (i.e. SSH Key plus Google Authenticator), if an user logins from WAN (from public network). However, if an user logins from LAN (local network), it just needs password or SSH Key for authentication.

    To archive this, I need to setup a new instance of sshd with Two-Factor Authentication. The original sshd remains unchange for LAN users. Moreover, I also need to install google-authenticator related packages.

    (Note: need to use root account to do below steps)

    1. install the google-authenticator
      apt-get install libpam-google-authenticator libqrencode3
    2. link sshd-second to sshd. The name of executable sshd-second will be used to load the corresponding PAM config.
      ln /usr/sbin/sshd /usr/sbin/sshd-second
    3. create sshd_config-second by copying from sshd_config
      cp /etc/ssh/sshd_config /etc/ssh/sshd_config-second
    4. update the sshd_config-second: Change the "Port" to 9022 (you can use any available port you want); change "ChallengeResponseAuthentication" to "yes"; Set "PasswordAuthentication" to "no"; add "AuthenticationMethods publickey,keyboard-interactive:pam" and add "PidFile /var/run/sshd-second.pid". Here shows the diff between /etc/ssh/sshd_config and /etc/ssh/sshd_config-second after edited:
      # diff sshd_config sshd_config-second 
      5c5
      < Port 22
      ---
      > Port 9022
      49c49
      < ChallengeResponseAuthentication no
      ---
      > ChallengeResponseAuthentication yes
      52c52,54
      < #PasswordAuthentication yes
      ---
      > PasswordAuthentication no
      > 
      > AuthenticationMethods publickey,keyboard-interactive:pam
      89a92
      > PidFile /var/run/sshd-second.pid
    5. create /etc/pam.d/sshd-second by copying from /etc/pam.d/sshd
    6. cp /etc/pam.d/sshd /etc/pam.d/sshd-second
    7. updte the /etc/pam.d/sshd-second: comment out the line "@include common-auth" and add a line "auth required pam_google_authenticator.so" after "@include common-auth". Here shows the diff between /etc/pam.d/sshd-second and /etc/pam.d/sshd after edited:
      # diff sshd sshd-second 
      4c4,5
      < @include common-auth
      ---
      > #@include common-auth
      > auth required pam_google_authenticator.so
      
      (I comment out the "common-auth" here because I don't want it prompts for password during login.)
    8. create /lib/systemd/system/sshd-second.service by copying from /lib/systemd/system/sshd.service
      cp /lib/systemd/system/sshd.service /lib/systemd/system/sshd-second.service
    9. edit /lib/systemd/system/sshd-second.service: Update the "Description"; update the "ExecStart" to "/usr/sbin/sshd-second -f /etc/ssh/sshd_config-second -D $SSHD_OPTS"; update the "Alias" to "sshd-second.service". Here shows the diff between sshd-second.service and sshd.service after edited:
      # diff sshd.service sshd-second.service 
      2c2
      < Description=OpenBSD Secure Shell server
      ---
      > Description=OpenBSD Secure Shell server (2nd)
      8c8
      < ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
      ---
      > ExecStart=/usr/sbin/sshd-second -f /etc/ssh/sshd_config-second -D $SSHD_OPTS
      15c15
      < Alias=sshd.service
      ---
      > Alias=sshd-second.service
    10. enable and start the new sshd instance:
      systemctl enable sshd-second
      systemctl start sshd-second
      
      (To check the status of the new sshd, you can run "systemctl status sshd-second")
    Up to now, the new sshd setup is done. Next, need to setup Google Authenticator for each users.
    1. Login as user and run "google-authenticator". Like below:
    2. On user's smart phone, open the Google Authenticator app. Then, add the account using the QRCode or input the secret key. (If the user's phone doesn't have the app, please follow this link to install).
    3. To test the login, use ssh command, e.g:
      ssh localhost -o Port=9022
      Then, it prompts for "Verification code". The user can get the code from the Google Authenticator App. As long as the user input the code correctly and with correct ssh-key, he/she can login.
    Last but not least, need to update router/firewall setting, such that it blocks the original sshd (port 22) from public network and opens for the port (9022 in my case) of the new sshd instance to be access from public network.

    [the demo environment is Raspbian GNU/Linux 8 (jessie)]

    Saturday, October 01, 2016

    Correct Way to Convert Local Time with DST to GMT/UTC in C

    The earth is round (not flat). Timezone and light saving handling is rocket science. Below is a program in C to demonstrate how to convert a string of local time in 'yyyy-mm-dd HH:SS' format to GMT/UTC time. Please note that line "27" is very critical. Without setting the tm_isdst to -1, DST won't be correctly converted.



     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #include <stdio.h>
    #include <time.h>
    #include <string.h>
    
    //input should be string of local time in 'yyyy-mm-dd HH:SS' format
    int printgmttime(const char * input)
    {
        struct tm localtm;
        struct tm gmttm;
        time_t timestamp;
        int rtval;
    
        memset(&localtm, 0, sizeof(struct tm));
    
        rtval = sscanf(input, "%4d-%2d-%2d %2d:%2d",
                &localtm.tm_year, &localtm.tm_mon, &localtm.tm_mday,
                &localtm.tm_hour, &localtm.tm_min);
    
        if (rtval < 5)
        {
            printf("unable to parse date time '%s'\n", input);
            return 1;
        }
    
        localtm.tm_year -= 1900; //tm_year = Year - 1900 
        localtm.tm_mon -= 1; //Month (0-11)
        localtm.tm_isdst= -1; //-1 means using system timezone info
    
        timestamp = timelocal(&localtm);
    
        gmtime_r(&timestamp, &gmttm);
    
        printf("GMT Date Time: %04d-%02d-%02d %02d:%02d\n",
                gmttm.tm_year+1900, gmttm.tm_mon +1, gmttm.tm_mday,
                gmttm.tm_hour, gmttm.tm_min);
        return 0;
    }
    
    int main(int argc, char** argv)
    {
        if (argc <= 1)
        {
            printf("Wrong number of argument\n");
            printf("Syntax:\n");
            printf("\t%s 'yyyy-mm-dd HH:SS'\n", argv[0]);
            return 1;
        }
    
        return printgmttime(argv[1]);
    }
    

    Friday, September 30, 2016

    WinMerge Alternative in Linux Terminal

    WinMerge is a good open source tool to compare text files, but it only runs in Windows platforms. When I need to compare text files in Linux terminal, I use vimdiff (Vim in diff mode). Actually, Emacs also has similar feature. However, I prefer Vim because it's more handy.

    To compare two files with vimdiff, you just need to run the vimdiff command with the path of the files you want to compare:
    vimdiff file1 file2
    Then, you will see something like below:
    You can edit the files as a normal Vim editor. However, I would like to highlight some useful commands in diff mode of vim:
    ]c
    Jump to next change
    ]c
    Jump to prev change
    do
    Update the current change by copying the change of another buffer.
    dp
    Update change of another buffer by copying the current change of this buffer.
    Ctrl-w Ctrl-w
    Switch to another buffer

    Wednesday, September 28, 2016

    VLC vs MPlayer for DVB playback with hardware decode (vdpau)

    Regularly, I have some TV programs been recorded with USB TV tuner. So, I need a program to playback the recorded videos in my Linux box. In Linux world, there are two popular video players -- VLC and MPlayer. I tried both, and here are my comments:

    • VLC provides better GUI. Although mplayer also provide GUI frontends, but they didn't works well. Some of the frontends can't even run. One of the frontend "SMPlayer" can run on my box, but it has some bugs which unable to display the subtitle of the recorded TV programs.
    • In terms of hardware decode, MPlayer works much more stable than VLC. VLC occasionally has errors on decoding and shows blank screen. 
      Decoding Errors of VLC
    Finally, I can only use the command line MPlayer. Here is the scripts to playback the videos:
    
    #!/bin/sh
    mplayer -vc ffh264vdpau,ffmpeg12vdpau,ffwmv3vdpau,ffvc1vdpau -vo vdpau:deint=3 -framedrop -ao pulse -dr -cache 8192 "$@"
    

    [Testing environment: XUbuntu 16.04, vlc 2.2.2-5, mplayer 2:1.2.1-1ubuntu1, smplayer 15.11.0~ds0-1, libvdpau1 1.1.1-3ubuntu1, vdpau-driver-all 1.1.1-3ubuntu1, Nvidia Linux Driver 367.44]

    Sunday, September 25, 2016

    Fine Tuning X Window Settings of My Desktop (Nvidia, Dual Mon, Xubuntu 16.04)

    Recently, I bought a new desktop and two new monitors. I spent some time to get them working nicely. So, I would like to share my story here.

    I installed Xubuntu 16.04 to the desktop. The display card is GeForce GTX 950. Then, I downloaded and installed the Nvidia Linux Driver. I run the Nvidia X Server Settings and export a xorg.conf file.


    Here was the "Screen" section of xorg.conf file:
    Section "Screen"
        Identifier     "Screen0"
        Device         "Device0"
        Monitor        "Monitor0"
        DefaultDepth    24
        Option         "Stereo" "0"
        Option         "nvidiaXineramaInfoOrder" "DFP-2.8"
        Option         "metamodes" "DP-0.8: nvidia-auto-select +0+503, DP-0.1.8: nvidia-auto-select +1920+0 {rotation=left}"
        Option         "SLI" "Off"
        Option         "MultiGPU" "Off"
        Option         "BaseMosaic" "off"
        SubSection     "Display"
            Depth       24
        EndSubSection
    EndSection
    You can see the "metamodes" was to setup the screen positions and rotation. Please note that the monitor on left is rotated.

    Basically, the Nvidia driver worked, but with some issues:
    1. Heavy tearing
    2. In text mode (i.e. alt-F1), the text is on the monitor rotated left. 
    After some googling on the web, issue 1 can be fixed by adding "ForceCompositionPipeline = On" in the metamodes. So, the "metamodes" becomes:
    "DP-0.8: nvidia-auto-select +0+503 {ForceCompositionPipeline = On}, DP-0.1.8: nvidia-auto-select +1920+0 {rotation=left, ForceCompositionPipeline = On}"
    
    However, issue 2 is bit tricky. After some trial-and-error, I found that the sequence of screens declare on the "metamodes"did the trick. The last screen shows the text in text mode. So, I swapped the DP-0.8 and DP-0.1.8 in the "metamodes":
    "DP-0.1.8: nvidia-auto-select +1920+0 {rotation=left, ForceCompositionPipeline = On}, DP-0.8: nvidia-auto-select +0+503 {ForceCompositionPipeline = On}"
    Now, it works perfectly.

    Sunday, July 20, 2014

    Trying Noto Font in Ubuntu 14.04

    Google and Adobe developed new Open Source fonts recently. I installed Noto Sans on my Ubuntu 14.04 Desktop. The screenshot below shows three different fonts displaying in a Facebook page in Chrome browser (Ver. 36.0.1985.125) in Ubuntu 14.04 Desktop. The upper screenshot is Google's Noto Sans Traditional Chinese font. Middle one is Microsoft JhengHei (a M$ font from Windows 7). The lower one is WenQuanYi Zen Hei (another open source font come with Ubuntu). You can see Noto Sans performs well. Now, I no longer need M$ fonts for my Linux box.




    Saturday, August 25, 2007

    MTU is really a matter

    Long time ago, I lower the MTU of my router to solve a networking issue (see my previous blog entry). However, it is not the end of story.
    Recently, I have changed my job. My new company provides Citrix Presentation Server for employees to work at home via remote desktop.
    Then, at home, I tried to connect to Citrix server and run remote desktop. I can login but the link is very unstable. It disconnected every 10 to 20 seconds.
    After some investigation, I found it is the MTU problem again. The problem is fully explained at the following site:
    http://www.netheaven.com/pmtu.html
    I should change the MTU of my desktop at home to match the router. Finally, it works!

    Sunday, July 01, 2007

    Boost C++ Libraries

    Recently, I checked some job ad. on the web and found some jobs require knowledge about "Boost". I have not heard "Boost" before. After some googling, I visit the web site of Boost. Boost is really a great thing. It is a set of C++ libraries contains many useful programming constructs with good documentation, e.g. smart pointers, regular expression, object pools, state machines.... Lastly, it is open source and free.

    Sunday, June 17, 2007

    Dig out dead looping thread

    It is not easy to write multi-threading applications. One of the common bugs is dead looping of a thread. To kill this kind of bugs, the first step is to find out which thread causes dead looping. However, an application may have dozens of threads. How to dig out the dead looping thread? My trick is to issue the ps -eLf command to list the information of threads in the whole system. The "time" column of the output of ps shows the CPU time have spent by the threads. Most likely, the dead looping thread would be the thread spending most CPU time. Then, drop down the LWP number of the thread. Next, you use gdb to attach the process and to debug the thread.