Personal tools
You are here: Home Data Concurrency bug patterns Case1

Case1

Two network events are executed in unexpected order

Description

A concurrency error of this example occurs when two network events are executed in unexpected order. The function image134Loaded in line 9 of case1.html is called when image1.jpg, image3.jpg or image4.jpg is downloaded. The function image134Loaded assigns an object to imagesList. The function image2Loaded in line 12 of case1.html is called when image2.jpg is downloaded. The function image2Loaded reads imagesList. If image2.jpg is downloaded before image1.jpg, image3.jpg and image4.jpg, imagesList is not initialized yet and the bug occurs.

Example

http://pswlab.kaist.ac.kr:81/case1.html

Reference

"Ajax race conditions create erroneous error messages" in Drupal, https://drupal.org/node/830386

"Relying on the order of asynchronous operations" in "Avoiding intermittent oranges", https://developer.mozilla.org/en-US/docs/Mozilla/QA/Avoiding_intermittent_oranges

Source code

case1.html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Case1</title>
</head>
<body>
<script>
function image134Loaded(elem) {
imagesList = {width:elem.width};
}
function image2Loaded() {
document.getElementById("outputImage2").innerHTML = "Width of images : " + imagesList.width;
}
function button1Clicked() {
document.getElementById("outputButton1").innerHTML = "Button 1 is clicked";
}
function button2Clicked() {
document.getElementById("outputButton2").innerHTML = "Button 2 is clicked";
}
</script>
<div id="outputImage2"></div>
<img id="image1" src="image1.jpg" onload="image134Loaded(this)" width="100px" height="75px" />
<img id="image2" src="image2.jpg" onload="image2Loaded()" width="100px" height="75px" />
<script src='dummy.js'></script><br />
<img id="image3" src="image3.jpg" onload="image134Loaded(this)" width="100px" height="75px" />
<img id="image4" src="image4.jpg" onload="image134Loaded(this)" width="100px" height="75px" /><br />
<button id="button1" onclick="button1Clicked()" >Button 1</button>
<button id="button2" onclick="button2Clicked()" >Button 2</button>
<div id="outputButton1" ></div>
<div id="outputButton2" ></div>
</body>
</html>

dummy.js

// dummy. works noting.
// dummy. works noting.
// dummy. works noting.

Execution Model

Operations and an Inital Test Case

There are 8 operations in this example.

  • p1: parsing operation, parse line 1~24 of case1.html
  • p2: parsing operation, parse dummy.js and line 25~33 of case1.html
  • n1: network operation, trigger onload event of image1.jpg
  • n2: network operation, trigger onload event of image2.jpg
  • n3: network operation, trigger onload event of image3.jpg
  • n4: network operation, trigger onload event of image4.jpg
  • u1: user event operation, trigger onclick event of button1
  • u2: user event operation, trigger onclick event of button2

The inital test case: p1 - p2 - n1 - n2 - n3 - n4 - u1 - u2

Happens-before Relations

  • For two parsing operations: (p1, p2)
  • For two user event operations: (u1, u2)
  • For a parsing operation and a user event operation: (p2, u1), (p2, u2)
  • For a network operation: (p1, n1), (p1, n2), (p2, n3), (p2, n4)

Generated Possible Test Cases

504 test cases are generated and 162 test cases of them are buggy because they contains (n2, n1), (n2, n3) and (n2, n4).

Document Actions