Skip to content
This repository has been archived by the owner on Jan 11, 2023. It is now read-only.

Processing data on serial queue to prevent data racing conditions #417

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

tifroz
Copy link
Contributor

@tifroz tifroz commented Mar 13, 2019

Note: data racing conditions can be detected when running the code with the Thread Sanitizer turned on (Thread Sanitizer can only be activated when running on simulators at least for iOS apps)

@swisspol
Copy link
Owner

What’s the race condition here? How do you reproduce?

This change will also prevent concurrent reading and writing on the connection.

@tifroz
Copy link
Contributor Author

tifroz commented Mar 14, 2019 via email

@swisspol
Copy link
Owner

swisspol commented Mar 14, 2019 via email

@tifroz
Copy link
Contributor Author

tifroz commented Mar 14, 2019

In the demo ViewController.swift, replace the definition for webServer and for viewWillAppear like so.

Then GET "/" (e.g. curl http://[gcdServerAddress]:8080/)

var webServer: GCDWebServer!

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    webServer = GCDWebServer()
    webServer.delegate = self
    webServer.addHandler(forMethod: "GET", path: "/", request: GCDWebServerRequest.classForCoder()) { [weak webServer]
      (gcdRequest:GCDWebServerRequest?, completion:GCDWebServerCompletionBlock?) -> Void in

      let contentLength: Int = 10000
      DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.5, execute: {
        let localResponse = GCDWebServerStreamedResponse(contentType: "application/data", asyncStreamBlock: { (bodyReaderBlock: GCDWebServerBodyReaderCompletionBlock?) -> Void in

          for index in 0..<contentLength {
            let buffer = "a".data(using: String.Encoding.utf8)!
            bodyReaderBlock?(buffer, nil)
          }
        })
        localResponse.statusCode = 200
        completion?(localResponse)
      })
    }
    
    if webServer.start() {
      label?.text = "Server running on port \(webServer.port).\n\nGET '/' to start test"
    } else {
      label?.text = "Server failed to start :("
    }
  }

@tifroz
Copy link
Contributor Author

tifroz commented Mar 18, 2019

The code above reproduced the issue for me without fault (with the Thread Sanitizer turned on ). Let me know if you can't reproduce / need me to make adjustments to the Pull Request?

@swisspol
Copy link
Owner

Thanks for sharing this, I'll give it a look when I get the chance.

@tifroz
Copy link
Contributor Author

tifroz commented May 22, 2021

@swisspol did you get a chance to look at this? I was about to create another PR to address issues detected by the static analyzer but I don't think I can create another fork without dumping the fork that this PR (#417) is based on.

I am totally ok if you'd rather dump this PR in order to move forward.

For context, I am adding a screenshot of the output of the static analyzer (2 issues: a nil function reference, and a memory leak). The fixes are pretty simple: in GCDWebServerConnection.m line 760, wrap the function call with if (_handler != nil) {}, and in GCDWebServer.m adding CFRelease(txtData); after line 613

Screen Shot 2021-05-22 at 2 50 04 PM

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants