1 / 78

Automated Atomicity-Violation Fixing

AFix detects and fixes single-variable atomicity violations efficiently, reducing deadlock risks and improving code readability /

edecoteau
Download Presentation

Automated Atomicity-Violation Fixing

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Automated Atomicity-Violation Fixing Jeremy Bo Tanima Lingmei

  2. Problem Fixing concurrency bugs is challenging Root cause Error-prone patches Serialization bottlenecks Many ideas for detection, but few for fixing

  3. Related Work Identification Force interleaving to identify problems Bug Fixing Concurrent program synthesis Infer synchronization based on user input Steer execution to avoid failure Hardware watch points

  4. Contributions Implement tool AFix which detects and fixes single variable atomicity violations Improve code readability Fix bugs without large performance degradation Minimal deadlock risk

  5. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1],str,str_len); buf_len=tmp; }

  6. Atomicity Violation: Example Buffer void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7

  7. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7

  8. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  9. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  10. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  11. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str,str_len); buf_len=tmp; } buf_len = 5 MAX = 7 tmp = 5

  12. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; }

  13. Atomicity Violation: Example Buffer void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7

  14. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7

  15. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  16. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  17. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } Input: str = JOE str_len = 3 buf_len = 2 MAX = 7 Input: str = SAM str_len = 3

  18. Atomicity Violation: Example Buffer Input: str = SAM str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  19. Atomicity Violation: Example Buffer Input: str = SAM str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  20. Atomicity Violation: Example Buffer Input: str = SAM str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  21. Atomicity Violation: Example Buffer Input: str = SAM str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 5 MAX = 7 tmp = 5

  22. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1],str,str_len); buf_len=tmp; } void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } Input: str = JOE str_len = 3 buf_len = 5 MAX = 7 Input: str = SAM str_len = 3

  23. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 5 MAX = 7 tmp = 5 ERROR

  24. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; }

  25. Atomicity Violation: Example Buffer Input: str = JOE str_len = 3 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 2 MAX = 7 tmp = 5

  26. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } Input: str = JOE str_len = 3 buf_len = 2 MAX = 7 Input: str = HI str_len = 2

  27. Atomicity Violation: Example Buffer Input: str = HI str_len = 2 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } buf_len = 4 MAX = 7 tmp = 4

  28. Atomicity Violation: Example void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; } Input: str = JOE str_len = 3 buf_len = 4 MAX = 7 Input: str = HI str_len = 3

  29. Atomicity Violation: Example Buffer Input: str = HI str_len = 2 void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len], str, str_len); buf_len=tmp; } buf_len = 5 MAX = 7 tmp = 5

  30. Background: CTrigger In-house tool to detect potential single variable atomicity violations Identifies potential violations via static analysis Prunes infeasible interleaving Ranks possible violations based on probability of occurrence Attempt to expose bugs via delays at specific points

  31. Background: CTrigger Terminology (p, c, r) triple: Preceding, current, remote two consecutive accesses (p, c) to the same variable in the same thread are interleaved by a remote access (r) by another thread Causes execution to differ from serial execution

  32. Background: CTrigger

  33. Background: CTrigger

  34. Background: CTrigger Modifications Output all possible combinations for c instructions Return complete call stack for p, c, and r Limitations Exposed bugs should not always use separate patches May not expose the root problem

  35. Naïve Fix Lock Require lock before p and r, release after c and r Lock Unlock Unlock

  36. Naïve Fix void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; }

  37. Naïve Fix void buf_write(…){ Lock int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); Unlock Lock buf_len=tmp; Unlock }

  38. Naïve Fix void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return memcpy(buf[buf_len+1], str, str_len); buf_len=tmp; }

  39. Naïve Fix void buf_write(…){ int tmp = buf_len+str_len; if(tmp > MAX) return Lock memcpy(buf[buf_len+1], str, str_len); Lock buf_len=tmp; Unlock Unlock }

  40. Contributions & Methodology

  41. Fixing Bug Report

  42. Fixing Strategy • Fix one bug report • a single atomicity violation • Fix multiple bug report • multiple bugs reported by bug detectors

  43. How AFix changes the code critical region 1 critical region 2 p c r avoid introducing new bugs? mutually exclusive

  44. m p c n q Single-Function Operation • Condition 1: assume the function is not recursive. • the set of protected nodes = • P∩C={p,c,m,q}∩{p,c,m,n,q}={p,c,m,q} • (2) Search backword from c, for each searching path, let out-degree(p)≤1 and in-degree(p)=0 • C={p,c,m,n,q} • (1) Search forward from p, for each searching path, let out-degree(c)=0 and in-degree(c)≤1 • P = {p,c,m,q}

  45. a b unreleased lock / potential deadlock lock; if(gPtr){ puts(gPtr); unlock; } else{ unlock; ... } unlock; insert unlock from protected nodes to unprotected nodes

  46. a a double lock and unlock without lock • while(...){ • lock; • ptr = aPtr; • } • puts(ptr); • unlock; lock; while(...){ insert lock from unprotected nodes to protected nodes

  47. Deadlock Analysis and Avoidance critical region pthread_mutex_timelock to acquire locks AFix statically analysis acuqire lock after maximum delay? Yes potentially-blocking operations? Yes No No pthread_mutex_lock to acquire locks continue program time out

  48. Single-Function Operation Condition 2: the function is recursive. • void foo(){ • lock; • ptr = aPtr; • if (...) foo(); • puts(ptr); • unlock; • } reentrant_lock; reentrant_unlock; reentrant lock avoids double lock mutex.owner: thread-ID mutex.count: nesting level

  49. Multiple-Function Operation • when p and c come from different functions • Problems: no detection? • Solution: • substitute p and c with the real call node in the innermost function.

  50. Harmonizing two critical regions-mutually exclusive critical region 2 critical region 1 p ... (r) ... c r if any of the calls in f (a function containing p&c) which lead to r are themselves inside the p-c critical region, then the lock operation of r is redundant and should be removed

More Related