brianmario/mysql2 — pull request #498 by sodabrew (2014-03-23 05:38:10+00:00)
Title: avoid redundant close from calling mysql_close

Pull request on behalf of Eric Wong.

Calling close redundantly on an FD means a race condition will break
multithreaded applications (or worse, lead to inadvertant
information disclosure). Consider the following multithreaded
timeline with two threads:

```
thread 1 (mysql2 close) | thread 2 (blocking accept loop)
---------------------------------+----------------------------------
close(9) -> fd=9 released |
| accept() -> fd=9 acquired
mysql_close -> close(9) |
# releases fd=9 which thread 2 |
# just took using accept() |
| read(9) -> EBADF!
```

We must prevent mysql_close from possibly hitting a recycled FD when
it calls close again. So we redirect the existing FD to a dummy
socket (atomically closing the original FD/socket in the process).
This means mysql_close will call close on a valid FD, but that FD
now points to a dummy socket and not a valid FD.

I considered using socketpair (to ensure write/shutdown inside
mysql_close succeeds), but decided against it as there may be
a chance the client library will one day wait for a disconnect
message from the server.

Thanks to Evan Miller for this idea.