title: cgo Interacting with C Library that uses Thread Local Storage
body: <p>I'm in the midst of wrapping a C library with cgo to be usable by normal Go code.</p>
  
  <p>My problem is that I'd like to propagate error strings up to the Go API, but the C library in question makes error strings available via thread-local storage; there's a global <code>get_error()</code> call that returns a pointer to thread local character data.</p>
  
  <p>My original plan was to call into C via cgo, check if the call returned an error, and if so, wrap the error string using <code>C.GoString</code> to convert it from a raw character pointer into a Go string. It'd look something like <code>C.GoString(C.get_error())</code>.</p>
  
  <p>The problem that I foresee here is that TLS in C works on the level of native OS threads, but in my understanding, the calling Go code will be coming from one of potentially N goroutines that are multiplexed across some number of underlying native threads in a thread pool managed by the Go scheduler.</p>
  
  <p>What I'm afraid of is running into a situation where I call into the C routine, then after the C routine returns, but before I copy the error string, the Go scheduler decides to swap the current goroutine out for another one. When the original goroutine gets swapped back in, it could potentially be on a different native thread for all I know, but even if it gets swapped back onto the same thread, any goroutines that ran there in the intervening time could've changed the state of the TLS, causing me to load an error string for an unrelated call.</p>
  
  <p>My questions are these:</p>
  
  <ul>
  <li>Is this a reasonable concern? Am I misunderstanding something about the go scheduler, or the way it interacts with cgo, that would cause this to not be an issue?</li>
  <li>If this is a reasonable concern, how can I work around it?
  
  <ul>
  <li>cgo somehow manages to propagate errno values back to the calling Go code, which are also stored in TLS, which makes me think there must be a safe way to do this.</li>
  <li>I can't think of a way that the C code itself could get preempted by the go scheduler, so should I introduce a wrapper C function and have IT make the necessary call and then conditionally copy the error string before returning back up to goland?</li>
  </ul></li>
  </ul>
  
  <p>I'm interested in any solution that would allow me to propagate the error strings out to the rest of Go, but I'm hoping to avoid any solution that would require me to serialize accesses around the TLS, as adding a lock just to grab an error string seems greatly unfortunate to me.</p>
  
  <p>Thanks in advance!</p>