Dynamic Software Updates: The State Mapping Problem
Rida A. Bazzi Kristis Makris Peyman Nayeri Jun Shen
ARIZONA STATE UNIVERSITY
The Software Update Problem• Replace an old version of an application with a
new version of the application
old new
old
new
old
newState mapping
1. How to affect the mapping: mechanism?2. How to determine if a safe mapping is
possible?
THE MECHANISM: UpStare• A general mechanism for state mapping• Supports immediate updates of multi-
threaded applications• Supports update for applications with blocking
system calls• An application written in C is made updateable
using code instrumentation
UpStare’s MECHANISMS• State Reconstruction: to update active
functions• Transforming blocking calls to non-blocking
calls.• Forcing all threads to block before an update.– Stack reconstruction for every thread– Resumption up to the update point for all– Resumption for all
STATE MAPPING in UpStare• Maps– global variables global variables– local variables local variables
• Default type transformation– short to long– Float to double– ....
• Default initialization• Can be overridden by user
TAMING THE STATE MAPPING PROBLEM
• Assumption– Some degree of backward compatibility should be
expected
• Approach– Ignore some differences: log functions– Reduce the state that needs to be mapped: wait for
light-weight functions to exit– Take advantage of backward compatibility assumption:
semantic checking with unification
LIGHT WEIGHT FUNCTIONS
• Functions that are guaranteed to exit in a bounded amount of time
• No need to map state!• We do not solve the halting problem
STRICT DEFINITION
• A function as lightweight if:• Does not contain loops• Does not call itself recursively• Does not call synchronization functions (locks,
semaphores, …)• Does not call a non-lightweight function• Does not read input
STRICT DETECTION• Initially, we have
– Lists of lightweight and heavyweight library functions– List of unknown library functions (we have not gone through all
of them yet)
• Any function that does not satisfy the strict definition is heavyweight
• Any function that calls a heavyweight function is heavyweight
• For the remaining functions:– Repeat until there are no changes: If a function only calls
lightweight functions, add it to the list of lightweight functions
LIGHT WEIGHT FUNCTIONS: INITIAL NUMBERS
Application Total Light Unknown Heavy
Apache 556 314 215 0
IceCast 692 346 131 215
OpenSSH 1334 455 879 0
PostgresSQL 5853 1236 4598 19
vsFTP 606 231 375 0
Moral: even simple analysis can go a long way
OTHER INTERESTING STATISTICS
Application Total Recursion Unknown Libary
Loops
Apache 556 6 193 88
IceCast 692 8 181 75
OpenSSH 1334 6 292 81
PostgresSQL
5853 141 215 371
vsFTP 606 2 124 15
LOG FUNCTIONS
• LOG-related functions: functions that write log files
• Disregard difference that are due to log function differences!!
LOG FUNCTIONS: DETECTION1. String arguments2. Write only (fprintf, printf (not persistent), write, …) 3. Heavily used: no. of callers * no. of call sites4. recursively : called by log-functions exclusively. This is
somewhat counter-intuitive and we should modify it to work bottom up.
5. Name has log (not logarithms!)
We can detect the “top” log function, but we miss some of them10% of changes are due to automatically detected log functions
ENHANCEMENTS: BACKWARD COMPATIBLE UPDATES
if (newOption)x = y*z;
elsex = y+z;
w = x/2;x = w-z;/* update point */(b) new version
x = y+z;
w = x/2;x = w-z;/* update point */(a) Old version
MAPPING FOR ENHANCEMENTS
• How to map state so that the execution after the update is equivalent to the execution before the update?
• For the example above: set NewOption to false • In general, we need to compare the semantics
of the two applications• Use of code slicing to compare the two
executions
CODE SLICING WITH UNIFICATION• Code slicing has been used to identify components that have
identical semantics• Our goal is different: we want to force to components to have
compatible semantics– Define basic compatibility rules to be used by unification procedure
• short to long• Float to double
– Define constructs that can match anything (NULL constructs)• Log functions for example
– Define patterns to handle control constructs• if (cond) then s1 else s2 matches s1 if cond (not unified yet) is true• if (x > y) then s1 bug fix!
BUG FIXES... ...
x = y+z;w = x/2;x = w-z;/* update point */(a) old version
... ...if (x > y)
x = y+z;w = x/2;x = w-z;/* update point */(b) new version
The state mapping is Impossible: cannot tell if x > yTrivial : disregard and hope for the best: this is the
update problem not the state repair problem!)
Not quite so!
BUG FIXES WITH CHECKPOINTING
• Checkpoint everywhere• Check x1 > y1 at the update point• Not practical!
... ...
x = y+z;w = x/2;x = w-z;/* update point */(a) old version
... ...if (x1 > y2)
x2 = y+z;w1 = x2/2;x3 = w2-z1;/* update point */(b) new version
BUG FIXES WITH CHECKPOINTING
• Checkpoint at– function entry– Interactions with environment
• Re-execute at time of update: should take relatively little time for non-compute bound applications – Assumes no change to interfaces with environment– Re-execution simulates interactions with environment
... ...
x = y+z;w = x/2;x = w-z;/* update point */(a) old version
... ...if (x > y)
x = y+z;w = x/2;x = w-z;/* update point */(b) new version
QUESTIONS?