Nmap Development mailing list archives

Re: [NSE] need to get waiting threads to resume after a thread having mutex dies


From: "Patrick Donnelly" <batrick.donnelly () gmail com>
Date: Thu, 7 Aug 2008 17:58:54 -0600

Hi Jah,

On Thu, Aug 7, 2008 at 4:30 PM, jah <jah () zadkiel plus com> wrote:
Hello,

If a thread that has a mutex finishes due to an error, threads waiting
for that mutex remain waiting for ever. Attached is an example which
needs to be run against two targets to illustrate the problem.
I've tried working this out for myself, but without success.  I feel
like someone who's picked-up a golf club for the first time, I'm just
hacking around.  Over to the pros I think.  I'll just watch.

Regards,

jah

id="bar"
author=""
runlevel="1"
description = ""

hostrule = function( host )
 return true
end

nmap.registry.foo = {}

action = function( host )

 print( ( "Thread for %s RUNNING.\n" ):format( host.ip ) )
 table.insert( nmap.registry.foo, host.ip )

 local mutex = nmap.mutex( id )


 print( ( "Thread for %s wants mutex.\n" ):format( host.ip ) )
 mutex "lock"
 print( ( "Thread for %s has mutex.\n" ):format( host.ip ) )

   if nmap.registry.foo[1] == host.ip then

     local sock = nmap.new_socket()
     sock:set_timeout( 0 )

     print( ( "Thread for %s yields briefly.\n" ):format( host.ip ) )
     status, error = sock:connect(host.ip, 80)
     sock:close()

     print( ( "Thread for %s has resumed and will now DIE horribly!" ):format( host.ip ) )

     -- this causes the thread to exit before it unlocks the mutex
     nmap.registry[nil] = 1

   end

 mutex "done"



 return table.concat( nmap.registry.foo, ", " )

end


The basic idea of a mutex (in a multi threading sense) is to provide
data consistency, coherency, and safety. If a thread dies, there is no
way for another thread to know what state the data is left in.
Therefore, allowing another thread to lock on the mutex and manipulate
the data will only lead to very odd and seemingly "impossible" bugs.
While generally these mutexes will not be used to protect against
asynchronous data manipulation, they could be; so it is best to
maintain a policy of "you break it, you get to keep both pieces".

It would be best for you to be certain that any errors are caught so
that your thread does necessary cleanup, such as unlocking a mutex
(and restoring the state of any data it protects). I assume you are
familiar with pcall[1], which will allow you to catch any errors that
are thrown. I also suggest that you always have your script prevent
itself from dying in an uncontrolled way (in that, NSE has to "clean
up after it"). A script that often errors over things like "Lua stack
overflow" or "attempt to concatenate a nil value" are not something a
user likely wants to see, even if it is rare.

[1] http://www.lua.org/manual/5.1/manual.html#pdf-pcall

Cheers,

-- 
-Patrick Donnelly

"One of the lessons of history is that nothing is often a good thing
to do and always a clever thing to say."

-Will Durant

_______________________________________________
Sent through the nmap-dev mailing list
http://cgi.insecure.org/mailman/listinfo/nmap-dev
Archived at http://SecLists.Org


Current thread: