cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
678
Views
15
Helpful
3
Replies

Assigning to self is not thread safe

u.avsec
Spotlight
Spotlight

Hi.

Situation in our service code is that certain objects like root, ncs.templateTemplate(service) and similar are used a lot which gets annoying dragging them through the code as necessary attributes.

So figured I could do things kinda like this:

 

class ServiceCallbacks(Service):
    def __init__(self, daemon, servicepoint, log=None, init_args=None):
        self.root: ncs.maagic.Root
        self.service: ncs.maagic.Node
        self.template: ncs.template.Template

        Service.__init__(self, daemon, servicepoint, log, init_args)
        
    @service.create
    def cb_create(self, tctx, root, service, proplist):
        self.root = root
        self.service = service
        self.template = Template(service)

 

(not exact code ... just to paint the picture)

Things run fine but I noticed warnings popping up in logs stating "Assigning to self is not thread safe".

I don't see us doing threading above whatever NSO might be doing out of the box, however, I'm wondering. We are on NSO 5.8.x, would this kind of stuff give us any headaches in future versions? Or in general, does this kind of approach cause headaches to anyone.

2 Accepted Solutions

Accepted Solutions

hazad
Cisco Employee
Cisco Employee

Yes it will give you headaches in NSO 6.0 and above, since service callbacks among other things will run in parallel as opposed to versions below where they are running sequentially protected by the transaction lock. Running multiple instances of that service callback in parallel will result in the self attributes being shared by the callbacks in a non thread safe manner. 

The warning has been added in 5.8 to prepare for this change.

View solution in original post

hazad
Cisco Employee
Cisco Employee

Using a dictionary or kwargs are good approaches. Another approach could be to create your own custom class holding all the service logic, and instantiate that class in the service create callback. You can in that class use self as much as you want which should be safe since you'll have a new instance of that class for each callback invocation.

View solution in original post

3 Replies 3

hazad
Cisco Employee
Cisco Employee

Yes it will give you headaches in NSO 6.0 and above, since service callbacks among other things will run in parallel as opposed to versions below where they are running sequentially protected by the transaction lock. Running multiple instances of that service callback in parallel will result in the self attributes being shared by the callbacks in a non thread safe manner. 

The warning has been added in 5.8 to prepare for this change.

I see. I was suspecting something like this.

Next question that arises would then be, what would be a suitable alternative to this (having instance wide available objects like root or service)? **kwargs or cramming them in a dictionary or something, I guess, but that isn't as nice as having stuff tucked away in self.

hazad
Cisco Employee
Cisco Employee

Using a dictionary or kwargs are good approaches. Another approach could be to create your own custom class holding all the service logic, and instantiate that class in the service create callback. You can in that class use self as much as you want which should be safe since you'll have a new instance of that class for each callback invocation.