diff --git a/docs/scripting.xml b/docs/scripting.xml index 0aa9ff4a5..45f5682b1 100644 --- a/docs/scripting.xml +++ b/docs/scripting.xml @@ -1271,93 +1271,88 @@ socket:close() threads in NSE mutexes in NSE - Each thread made for a script (e.g. ftp-anon) will yield to other - scripts whenever it makes a call on network objects (sending/receiving - data). Some scripts need finer control over threads' execution. An + Each script execution thread (e.g. ftp-anon running against an FTP server on the target host) yields to other + scripts whenever it makes a call on network objects (sending or receiving + data). Some scripts require finer concurrency control over thread execution. An example is the whois script which queries whoiswhois - servers for each target. Because many concurrent queries often result in - getting one's IP banned for abuse and a query may return additional + servers for each target IP address. Because many concurrent queries often result in + getting one's IP banned for abuse, and because a single query may return additional information for targets other threads are running against, it is useful - to have other threads pause while one thread is conducting a query. + to have other threads pause while one thread performs a query. - To solve this problem, there is an nmap function, - mutex, that provides a + To solve this problem, NSE includes a + mutex function which provides a mutex - usable by scripts. The mutex allows for only one thread to be working - on an object. Threads waiting to work on this object are put in the - waiting queue until they can get a "lock" on the mutex. A solution for - the whois problem above is to have each thread - block on a mutex using a common string, - thus ensuring only one thread is working so its results can - be shared with other scripts which may not need to run and so queries - to the whois servers are staggered. + (mutual exclusion object) usable by scripts. The mutex allows + for only one thread to be working on an object. Competing threads + waiting to work on this object are put in the waiting queue + until they can get a "lock" on the mutex. A solution for + the whois problem above is to have each + thread block on a mutex using a common string, thus ensuring + that only one thread is querying whois servers at once. That + thread can store the results in the NSE Registry before + releasing unlocking the mutex. The next script in the waiting + queue can then run. It will first check the Registry and only + query whois servers if the previous results were insufficient. + + The first step is to create a mutex object using a statement such as: + + mutexfn = nmap.mutex(object) + + The mutexfn returned is a function + which works as a mutex for the object passed + in. This object can be any + Lua data + type except nil, + booleans, and numbers. + The returned function allows you to lock, try to lock, and + release the mutex. Its first and only parameter must be one of + the following: + + - - - - - - - Returns a function that works on a mutex for the object passed. - This object can be any - - Lua data type - except nil, - booleans, and numbers. - The returned function allows you to lock, try to lock, and - release the mutex. Its first and only parameter must be one of the following: - - - - - "lock"—Make a blocking lock on the - mutex. If the mutex is busy - (another thread has a lock on it), then the thread will - yield and wait. The function returns with the mutex - locked. - - - - - "trylock"—Makes a non-blocking lock - on the mutex. If the mutex is - busy then it immediately returns with a return value of - false. Otherwise the mutex locks the - mutex and returns true. - - - - - "done"—Releases the mutex and allows - another thread to lock it. - If the thread does not have a lock on the mutex, an - error will be raised. - - - - - "running"—Returns the thread locked - on the mutex or nil if the mutex is not - locked. This should only be used for debugging as it - interferes with finished threads from being - collected. - - - - + "lock" + Make a blocking lock on the mutex. If the mutex is busy (another thread has a lock on it), then the thread will yield and wait. The function returns with the mutex locked. - + + + "trylock" + Makes a non-blocking lock on the mutex. If the mutex is + busy then it immediately returns with a return value of + false. Otherwise the mutex locks the + mutex and returns true. + + + + "done" + Releases the mutex and allows + another thread to lock it. If the thread does not have a lock on the mutex, an + error will be raised. + + + + "running" + Returns the thread locked + on the mutex or nil if the mutex is not + locked. This should only be used for debugging as it + interferes with garbage collection of finished threads. + + + +A simple example of using the API is provided in . For real-life examples, read the asn-query.nse and whois.nse scripts in the Nmap distribution. + Mutex manipulation local mutex = nmap.mutex("My Script's Unique ID"); function action(host, port) mutex "lock"; - -- do stuff + -- Do critical section work - only one thread at a time executes this. mutex "done"; return script_output; end