2.13.2Multithreading safety

Multithreading can break things

Falcon won't try to recover from multithreading errors done by the scripts. This means that an ill designed script can deadlock, mess up embedding application data and break in the most funny ways. If a script deadlocks, you won't be able to destroy its VM from an application and recover its resources; when a multithreaing thing (real full system level MT) in your application goes wild, your application is done for good. This even if the thing is a script encapsulated in a scripting engine.

Also, this is not just unavoidable (don't believe in who says it can be avoided), but also desirable. When a MT problem happens, this leaves (or may have leaved) the application in an unconsistent state, an thus it may create errors in other parts of the application, or produce inconsistent results. If the application forcefully clears the inconsistent status of the MT sublayer, i.e. by forcefully releasing a mutex in deadlocked state, this has an high (and unmanageable) change to cause an unforecastable and possibly undetectable error somewhere else.

As an example, think of a generic algorithm that locks a mutex, changes the name and the surname in a record and unlocks the mutex. Just, let's suppose we are able to change the name, but the surname is too long and the update method raises an exception. With automatic unlock, we'd have something like the following:


      // this is pseudo code; we're using a java/c# like syntax
      void updateRecord( String name, String surname )
                         throws something
      {
         AutoLock locker( this.mutex );
         this.setName( name );
         this.setSurname( surname ); // throws the exception.
      }

In the above example we ipotized an AutoLock class that locks a mutex, then unlocks it at stack unroll.

Now, that guard ensure that we release the mutex at function exit, no matter how it exits. Pitifully, it can't grant data to be consistent. In example, we may have set our record to a new name, "Adam aVeryVeryLongStrangerSurname", and get the exception on the surname. Adam will be stored, and we'll have something as an unexistent "Adam Smith" in our database. We broken our data, and we may know that much later, in example when Mr. aVeryVeryLong...etc, our boss, fires us because we didn't send him his montly wage payroll, but "yo, ye mutex is unlocked"!

Of course, we could have gotten the exception and fix things; but while we were fixing things we may also have properly released the mutex when it was consistent to do it.

But the point is another. If we made such an error as forgetting to take care of the dirty record above, then the most immediate and effective diagniostic is that of being locked on it. Compare the above with this code:


   // this is pseudo code; we're using a java/c# like syntax
   void updateRecord( String name, String surname )
                        throws something
   {
      this.mutex.lock();
      this.setName( name );
      this.setSurname( surname ); // throws the exception.
      this.mutex.unlock();
   }

The logic error is the same as above. We have broken the name, but now the MT layer is in inconsistent state, and the next lock to the mutex will cause the application to deadlock. Provided mutexes are used rationally, this means that we'll have a clear indication of what appened in the early stages of development.

Everyone forgets to unlock mutexes, at spots, and when it happens it hurts, because you feel like an idiot. Feeling like an idiot is the worst thing for a programmer. This is very probably the reason why such automatic one-line savers have been invented. However, clearing the MT layer status without being able to be sure that the application built on the MT layer is clear too is a very dangerous operation.

As such, Falcon doesn't provide it. If you acquire a synchronized structure you have to explicitly release it, or it won't be available for others to be acquired again. This is because it would be impossible, for Falcon, to know which part of the application state has been left inconsistent together with the synchronization structure. If Falcon release a shared resource in behalf of a failing thread, this may cause other working threads to use the shared data that was half worked and incomplete, and this may lead to disasters that are far worse than deadlock.

The correct approach to MT failures is not that to hide them or to automatically "fix" (hide) them, it is that to cure the program generating them so that they don't happen anymore.

Multithreading can break things (again)

We said that that an ill designed script can deadlock, mess up embedding application data and break in the most funny ways.

This means that embedding applications must be carefull in allowing their scripts to use threads. In case of security sensible applications, the threading module should be pre-loaded by the application and provided only to those scripts that have an administrative or equivalent security level. Only trusted scripts should be allowed to run MT in a production environment.

Made with http://www.falconpl.org