Thứ Năm, 25 tháng 10, 2018

Sơ suất do viết code rườm rà khiến chương trình bị crash

Lesson learn.

Trong quá trình viết một tính năng mới cho sản phẩm tôi đang làm tôi đã gặp phải một lỗi nhỏ nhưng gây hậu quả nghiêm trọng cho ứng dụng của tôi. Chính vì vậy nên tôi viết lại bài này để mô tả việc tôi đã tìm và sửa lỗi như thế nào.

Chuyện là tôi đang viết một ứng dụng định kỳ (cho sản phẩm tôi đang làm) thực hiện tác vụ kiểm tra kết nối giữa hai thiết bị để bật tắt đèn LED trên thiết bị của tôi theo từng trại thái kết nối tương ứng.
Khi tôi hoàn thành việc viết code demo và chạy thử thì bỗng dưng phát hiện ứng dụng của tôi chỉ chạy được lần đầu lần chạy tiếp theo nó đã bỗng dưng chết bất đắc kỳ tử với một mớ log của kernel bắn ra như sau:

ledwifictl:error:67.867:checkPledwifictl/512: potentially unexpected fatal signal 11.

Cpu 0
$ 0   : 00000000 10008400 00000000 ffff0000
$ 4   : 00000001 00400000 00000000 00000001
$ 8   : 00000000 fffffffe 00000000 6b486f73
$12   : 2066756e 00000800 00000400 6374696f
$16   : 00400000 7fa75a14 00400000 00400000
$20   : 7fa75d60 00400000 00401f5c 00409c08
$24   : 00000003 77758570                 
$28   : 0041a120 7fa759e8 004096a8 0040137c
Hi    : 00000001
Lo    : 00000000
epc   : 004014a4 0x4014a4
    Tainted: P           
ra    : 0040137c 0x40137c
Status: 00008413    USER EXL IE
Cause : 00000008
BadVA : 00000008
PrId  : 00029033 (Broadcom BMIPS3300)
airedHostWiFi:242:NBQ: ledctl PAIR on

 ở trong chương trình mà tôi viết có hai hàm thực hiện hai chức năng khác nhau, một hàm là checkPairedHostWiFi() dùng để kiểm tra xem thiết bị WiFi của tôi đã kết nối với Router được chưa nhằm bật/tắt LED. Hàm còn lại là hàm checkHostWiFiConnecting() thực hiện quét sóng WiFi của router để hiển thị đèn LED tương ứng với giá trị RSSI của sóng WiFi của Router đang kết nối tới.
Sau khi thấy lỗi xuất hiện với dòng log "ledwifictl:error:67.867:checkPledwifictl/512: potentially unexpected fatal signal 11." tôi cứ chắc mẫm là lỗi phải nằm trong hàm checkPairedHostWiFi() thế là hì  hục đặt log vào các vị trí trong hàm này để tìm lỗi. Tuy nhiên sau rất nhiều lần build firmware thay đổi các vị trí đặt log tôi vẫn chưa thể tìm ra nguyên nhân. Chán nản, tôi cảm thấy nghi ngờ dự đoán của mình. Vậy là tôi quyết định comment lời gọi hàm của hàm này và build lại firmware để chạy thử thì thấy lỗi vẫn còn đó. Từ đó tôi đã chuyển nghi ngờ của mình sang hàm checkHostWiFiConnecting() và tiến hành comment lời gọi hàm này và kết quả đã như dự đoán. Lỗi đích thị là do hàm này. Tôi tiến hành nhìn vào hàm mà mình đã viết, ôi thôi thật là rối rắm.


static int checkHostWiFiConnecting(void)
{
    FILE *pFile;
    char line[256] = {0};
    char cmd[64] = {0};
    char *result = NULL;
    WlVirtIntfCfgObject *intfObj = NULL;
    WlBaseCfgObject *wlBaseCfgObj = NULL;
    char rssi[4] = {0};
    int rssi_int = 0;

    if ((cmsLck_acquireLock()) != CMSRET_SUCCESS)
    {
        cmsLog_error("failed to get lock");
        cmsLck_dumpInfo ();
    }
    else
    {
        if ((getWlBaseCfgObjParams(&wlBaseCfgObj)) != CMSRET_SUCCESS)
        {
            cmsLck_releaseLock();
            return 0;
        }

        if ((1 != wlBaseCfgObj->wlEnbl) || (1 != wlBaseCfgObj->wlEnableUre))
        {
            cmsLck_releaseLock();
            return 0;
        }
        else
        {
            if (CMSRET_SUCCESS != getWlVirtIntfCfgObjParams(1, &intfObj))
            {
                cmsLog_error("Failed to get intfObj1");
                cmsObj_free((void **) &wlBaseCfgObj);
                cmsLck_releaseLock();
                return 0;
            }
            else
            {
                if (intfObj->wlEnblSsid == 0)
                {
                    cmsLck_releaseLock();
                    return 0;
                }
            }
        }
    }
    cmsLck_releaseLock(); /*Thì ra lỗi là do tôi thiếu dòng này cho nên chương trình chưa thực hiện release lock dẫn đến lần gọi hàm sau chương trình bị crash ngay lập tức*/
    sprintf(cmd, "wlctl scan --ssid=%s", intfObj->wlSsid);
    prctl_runCommandInShellBlocking ((char*)cmd);
    sleep(1);
    prctl_runCommandInShellBlocking ("wl scanresults > /var/tmp/wl_scanresults 2> /dev/null");

    cmsObj_free((void **) &wlBaseCfgObj); /*don't need it anymore*/
    cmsObj_free((void **) &intfObj); /*don't need it anymore*/
    pFile = fopen("/var/tmp/wl_scanresults", "r");
    if (!pFile)
    {
        cmsLog_error("Error open file.\n");
    }
    else
    {
        while (fgets(line, 256, pFile) != NULL)
        {
            result = strstr(line, "RSSI:");
            if (result != NULL )
            {
                sscanf(result, "RSSI: %s", rssi);
                fclose(pFile);
                rssi_int = atoi(rssi);
                if (rssi_int > -50)
                {
                    prctl_runCommandInShellBlocking ("ledctl NET on");
                }
                else if ((rssi_int < -50) || (rssi_int > -60))
                {
                    prctl_runCommandInShellBlocking ("ledctl NET blink");
                }
                else
                {
                    prctl_runCommandInShellBlocking ("ledctl NET off");
                }
                return 1;
            }
            else
            {
                continue;
            }
        }
        fclose(pFile);
    }
    return 0;
}
Tôi đọc lại hàm này thật kỹ thì phát hiện rằng do đoạn code rối rắm mà tôi đã quên thực hiện release lock cho trường hợp đọc các tham số thành công dẫn đến chương trình khi chạy lần thứ hai nó lại tiếp tục thực hiện requireLock và gây crash chương trình.
Vậy là chỉ một sơ suất nhỏ đã khiến tối mất khá nhiều thời gian không đáng có để sửa lỗi cho chương trình của mình.



Thứ Bảy, 11 tháng 1, 2014

Ba câu chuyện cuộc đời của huyền thoại Steven Job

Ba câu chuyện cuộc đời của huyền thoại Steven Job

Nói một cách trung thực nhất thì thực ra, tôi chưa bao giờ học đại học. Ngày hôm nay, tôi muốn kể cho các bạn nghe ba câu truyện đã từng xẩy ra trong cuộc đời tôi. Chỉ như vậy thôi, không có gì to lớn, chỉ đơn giản là ba câu truyện - đó là những gì huyền thoại công nghệ Steven Job bắt đầu câu chuyện của mình trong một bài phát biểu tại Đại học Stanford.
Câu chuyện thứ nhất là về việc kết nối những dấu chấm

Thứ Tư, 20 tháng 11, 2013

Khóa và ẩn thư mục bằng Anvide Lock Folder

Anvide Lock Folder, một ứng dụng miễn phí và không cần cài đặt giúp người dùng nhanh chóng khóa và ẩn thư mục một cách dễ dàng

Với các dữ liệu cá nhân và quan trọng được lưu trữ trên máy tính, chắc hẳn bạn sẽ không an tâm nhất là khi máy tính được sử dụng bởi nhiều người. Lúc này thì có thể bạn sẽ phải nhờ đến các ứng dụng giúp ẩn và khóa truy cập thư mục cùng các tập tin dữ liệu bên trong.
Ẩn và bảo vệ thư mục bằng mật khẩu dễ dàng trên Windows

Chủ Nhật, 10 tháng 11, 2013

Tư Duy Lô-gic

Tư Duy Lô-gic

LOGICAL THINKING

Logical thinking is a key to making sound decisions and solving complex problems. In this lesson, we will examine a few facets of logic in hope of helping you become a better thinker and problem-solver. Today, we will discuss some basic ideas about premises and conclusion, explore methods of logical arguments, analyze data, and use logic in solving puzzles.

Human beings have ability of thinking, but they do not always reason correctly. The science of correct reasoning is called logic. An understanding of logic will help you correctly arrange supporting evidence that leads to a conclusion.

Lời Khuyên Về Đắc Nhân Tâm

Luyện đọc tiếng anh


Lời Khuyên Về Đắc Nhân Tâm



TIPS FOR HOW TO BE POPULAR
To learn how to be popular, you must learn to be a good friend. That’s easier than you think.
What does it mean to be popular? Does it mean having the perfect clothes and the perfect hair? Being popular doesn’t mean being perfect; it means being well-liked by one’s peers. There is no magic trick to being popular, nor is it some elusive quality that only the most attractive and best-dressed can achieve.

Thứ Sáu, 1 tháng 11, 2013

Đàn ông-nếu đã 20, nếu chưa 25...



Đàn ông-nếu đã 20, nếu chưa 25



Tác giả: Lý Khai Phục từng là Phó tổng giám đốc Microsoft toàn cầu trong thập kỷ 90, rồi đảm nhận Phó tổng giám đốc Google châu Á năm 2005. Ông sinh năm 1961 tại Đài Bắc, thường gây sóng gió bởi những phát ngôn sáng suốt nhưng ngôn từ trần trụi khó nghe.
Nếu bạn là đàn ông, nếu bạn đã hai mươi, nhưng bạn chưa hai lăm tuổi, bạn buộc phải tìm được một thứ gì đó ngoài tình yêu, giúp đôi chân bạn đứng vững vàng trong cuộc đời này. Bạn phải bắt đầu nghĩ cách để kiếm ĐỦ và sống ĐƯỢC.
Tôi chưa từng bao giờ nghĩ bằng cấp là thứ quan trọng, thiên tài với danh nhân đâu phải từ lò luyện và trường lớp mà ra. Nhưng nếu bạn không học tới nơi tới chốn, thì dù có đi làm cửu vạn, ngay cả bao cát cũng sợ rằng chẳng biết cách mà vác.

Thứ Tư, 16 tháng 10, 2013

Ngắt trong 8051

(Tiếp tục phần ngắt trong 8051)

1.2 Sáu ngắt trong 8051

            Thực tế chỉ có 5 ngắt dành cho người dùng trong 8051 nhưng các nhà sản xuất nói rằng có 6 ngắt vì họ tính cả lệnh RESET. Sáu ngắt của 8051 được phân bố như sau:

1.      RESET: Khi chân RESET được kích hoạt từ 8051, bộ đếm chương trình nhảy về địa chỉ 0000H.  Đây là địa chỉ bật lại nguồn.
2.      2 ngắt dành cho các bộ định thời: 1 cho Timer0 và 1 cho Timer1. Địa chỉ tương ứng của các ngắt này là 000BH và 001BH.
3.      2 ngắt dành cho các ngắt phần cứng bên ngoài: chân 12 (P3.2) và 13 (P3.3) của cổng P3 là các ngắt phần cứng bên ngoài INT0 và INT1 tương ứng. Địa chỉ tương ứng của các ngắt ngoài này là 0003H và 0013H.
4.      Truyền thông nối tiếp: có 1 ngắt chung cho cả nhận và truyền dữ liệu nối tiếp. Địa chỉ của ngắt này trong bảng vector ngắt là 0023H.

Sơ suất do viết code rườm rà khiến chương trình bị crash

Lesson learn. Trong quá trình viết một tính năng mới cho sản phẩm tôi đang làm tôi đã gặp phải một lỗi nhỏ nhưng gây hậu quả nghiêm trọng ...