Special Configurations

Special Configurations #

Exclude Uninteresting Code Paths #

This tutorial assumes that you have gone through one of the three starter case tutorials and have successfully run Coderrect.

By default, Coderrect traverses every function that is reachable from the main function (or from any of the user-specified entry functions). However, in many cases, users might regard certain functions as uninteresting in their own projects and therefore do not want Coderrect to analyze those functions. This can be done by setting configuration for “skipFunctions” in .coderrect.json:

//.coderrect.json
"skipFunctions":[
        "print_msg"
] 

In the above example, the function “print_msg” will not be analyzed by Coderrect.


Analyzing Interesting Indirect Calls #

This tutorial assumes that you have gone through one of the three starter case tutorials and have successfully run Coderrect.

To make Coderrect fast, in the default setting Coderrect only analyzes a limited number of indirect function calls (functions that are invoked through function pointers) for each call site. It is because that the number of targets that can be pointed by the function pointer can be large and analyzing each of them is time-consuming. This works well for common cases in practice. However, in cases where a call site has many targets, users can configure “indirectFunctions” to analyze all possible targets called in a function. For example:

"indirectFunctions":[
        "OpBase_Consume"
] 

In the above, OpBase_Consume is a function from RedisGraph and it contains an indirect call op->consume(op) with a large number of possible call targets:

inline Record OpBase_Consume(OpBase *op) {
        return op->consume(op);
}

The configuration instructs Coderrect to analyze all possible indirect call targets in the function “OpBase_Consume“.


Define Custom Lock APIs #

Quick Start

To make Coderrect understand your custom lock APIs, please open your configuration file (the default one is $installDir/conf/coderrect.json), and add the following lines:

{
        ... ...
        lockUnlockFunctions: {
            "MyMutexLockFunc": "MyMutexUnlockFunc",
            "MySpinLockFunc": "MySpinUnlockFunc"
        }
}

Introduction

Lock APIs (e.g. pthread_mutex) are the most common synchronization mechanism used by developers. Coderrect has the built-in support for std::lock, std::mutex, pthread_mutex, and pthread_spin_lock. However, developers may use third-party libraries that have their own lock APIs. Furthermore, developers may create their own lock APIs to fit the special needs. 

Coderrect relies on the configuration “lockUnlockFunctions” to recognize these proprietary APIs.

lockUnlockFunctions

The code below creates a naive custom spin lock and protects simultaneous access to the global variable “x” by using it. 

#include <iostream>
#include <atomic>
#include <thread>

struct my_spinlock_t {
    std::atomic<bool> a;

    my_spinlock_t() : a(false) {}
};

void MySpinLock(my_spinlock_t* lock) {
    bool expected = false;
    while (!lock->a.compare_exchange_strong(expected, true))
    ;
}

void MySpinUnlock(my_spinlock_t* lock) {
    lock->a = false;
}

my_spinlock_t lock;
int x;


void thread_function() {
    MySpinLock(&lock);
    x++;
    std::cout << x << "n";
    MySpinUnlock(&lock);
}


int main ()
{
    std::thread first (thread_function);
    std::thread second (thread_function);
    first.join();
    second.join();
    return 0;
}

Let’s run Coderrect with the default configuration:

Coderrect detects a race because it doesn’t understand the meaning of MySpinLock and MySpinUnlcok and determines “x” are accessed by two threads simultaneously without synchronization.

Now, let’s tell Coderrect the meaning of MySpinLock/MySpinUnlock with a custom local configuration file lockunlockfunc.json:

{
    "lockUnlockFunctions": {
         "MySpinLock": "MySpinUnlock"
    }
}

The lockUnlockFunctions is a list of key-value pairs. Each pair has the name of the lock function as the key and the name of the unlock function as the value.

Let’s apply this configuration file to Coderrect and try again

You tell Coderrect to load and overlap the configuration file “lockunlockfunc.json” to the default coderrect.json using “-conf” option. Now, Coderrect knows MySpinLock and MySpinUnlock are a pair of lock-unlock functions and makes correct reasoning of the thread interleave.

Support Version

Coderrect 0.7.0+


Common Configurations #

HOW TO CUSTOMIZE CODERRECT DETECTION #


Coderrect Scanner provides a suite of configurations to help you focus on the most important issues.

Config Coderrect to skip specified functions during race analysis.
"skipFunctions":[ 
"FunctionName*", 
"FunctionOther" 
]

By default, Coderrect traverses every function that is reachable from the main function (or from any of the user-specified entry functions). In many cases, users might regard certain functions as uninteresting and therefore do not want Coderrect to analyze them.

Config Coderrect to skip analysis on specified variables.
"ignoreRaceVariables":[
"VariableName*",
"VariableOtherName" 
]

Check out a tutorial uses this configuration here
Specify a list of custom lock/unlock APIs so that Coderrect can make correct reasoning.
"lockUnlockFunctions": {
"MySpinLock": "MySpinUnlock",
"MyMutexLock": "MyMutexUnlock" 
}
Check out a tutorial uses this configuration here

HOW TO ANALYZE A LIBRARY #


Coderrect Scanner can analyze a library without a main function

Specify entry points for libraries in the configuration file:
"openlib": {
"entryPoints":[
"FunctionName*",
"FunctionNameOther" 

}
Check out a tutorial uses this configuration here

Powered by BetterDocs