Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

is curl_global_init handled safely? is the library thread-safe? #62

Open
divinity76 opened this issue Dec 16, 2017 · 6 comments
Open

is curl_global_init handled safely? is the library thread-safe? #62

divinity76 opened this issue Dec 16, 2017 · 6 comments

Comments

@divinity76
Copy link

divinity76 commented Dec 16, 2017

is the library supposed to be thread safe? note that curl_global_init() is NOT thread-safe, and curl_easy_init is threadsafe ONLY IF curl_global_init() has already been executed. if you start several threads that all call curl_easy_init() at the same time, before curl_global_init has been executed, you may run into problems, how does this reflect on go-curl?

@andelf
Copy link
Owner

andelf commented Mar 13, 2018

go-curl is not supposed to be thread safe.
I haven't figured out How to restrict func calling order.

@divinity76
Copy link
Author

divinity76 commented Mar 13, 2018

@andelf
do something like

var curl_global_inited bool = false

func go_curl_global_init() {
	var once sync.Once
	onceBody := func() {
		// call the real curl_global_init() here, and when done:
		curl_global_inited = true
	}
	once.Do(onceBody)
	for curl_global_inited != true {
		// some thread is running curl_global_init, wait for it to finish. 
		// optimization notes, figure out if Go has built-in support for "wait until variable changes", and if 1 millisecond is a sane timeout?
		time.Sleep(1 * time.Millisecond)
	}
}

and have all applicable functions call go_curl_global_init(), then go-curl should be thread-safe. as for performance, you'll have the function call overhead, but the time.Sleep code should only ever be hit in situations where you would actually have race condition without it, and will only run at the very first curl function calls, if ever, so i don't think it is a significant performance hit.

also, i hope there's a way to make curl_global_inited a function-local static threads-shared variable, but i don't know. (ps, i'm not proficient with Go myself, only toyed with it)

@umurkontaci
Copy link
Contributor

You can also use init function to load a module, that should load it only once.

Example: https://github.com/umurkontaci/go-curl-transport/blob/master/transport/transport.go#L21-L23

@divinity76
Copy link
Author

divinity76 commented Mar 13, 2018

@umurkontaci will that also help protect threads from calling curl_easy_init() before the thread calling curl_global_init() has completed the call?

@umurkontaci
Copy link
Contributor

Possibly, init is executed as the first thing when you import a module. But also it's quite possible to execute curl_easy_init before you import a specific module.

If you import the module in the application entrypoint you would probably be okay, but it's quite hacky way to do. It'd be better to encapsulate everything together.

@divinity76
Copy link
Author

actually, if you go with the sync.Once.Do method, you don't have to do the for curl_global_inited != true loop at all, because sync.Once.Do blocks other callers until it has executed completely. (according to guys on irc://irc.freenode.net/#go-nuts , anyway)

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

No branches or pull requests

3 participants