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

SNOW-903604 Zombie dbus processes generated by one of our dependencies github.com/99designs/keyring #1058

Merged
merged 5 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Support

For official support and urgent, production-impacting issues, please [contact Snowflake Support](https://community.snowflake.com/s/article/How-To-Submit-a-Support-Case-in-Snowflake-Lodge).

# Go Snowflake Driver

<a href="https://codecov.io/github/snowflakedb/gosnowflake?branch=master">
Expand Down Expand Up @@ -45,7 +49,7 @@ For detailed documentation and basic usage examples, please see the documentatio

# Sample Programs

Snowflake provides a set of sample programs to test with. Set the environment variable ``$GOPATH`` to the top directory of your workspace, e.g., ``~/go`` and make certain to
Snowflake provides a set of sample programs to test with. Set the environment variable ``$GOPATH`` to the top directory of your workspace, e.g., ``~/go`` and make certain to
include ``$GOPATH/bin`` in the environment variable ``$PATH``. Run the ``make`` command to build all sample programs.

```
Expand Down Expand Up @@ -93,7 +97,7 @@ make test

## Capturing Code Coverage

Configure your testing environment as described above and run ``make cov``. The coverage percentage will be printed on the console when the testing completes.
Configure your testing environment as described above and run ``make cov``. The coverage percentage will be printed on the console when the testing completes.

```
make cov
Expand All @@ -111,8 +115,15 @@ go tool cover -html=coverage.txt

You may use your preferred editor to edit the driver code. Make certain to run ``make fmt lint`` before submitting any pull request to Snowflake. This command formats your source code according to the standard Go style and detects any coding style issues.

## Support
## Runaway `dbus-daemon` processes on certain OS
This only affects certain Linux distributions, one of them is confirmed to be RHEL. Due to a bug in one of the dependencies (`keyring`),
on the affected OS, each invocation of a program depending on gosnowflake (or any other program depending on the same `keyring`),
will generate a new instance of `dbus-daemon` fork which can, due to not being cleaned up, eventually fill the fd limits.

Until we replace the offending dependency with one which doesn't have the bug, a workaround needs to be applied, which can be:
* cleaning up the runaway processes periodically
* setting envvar `DBUS_SESSION_BUS_ADDRESS=$XDG_RUNTIME_DIR/bus` (if that socket exists, or create it) or even `DBUS_SESSION_BUS_ADDRESS=/dev/null`

For official support, contact Snowflake support at:
[https://support.snowflake.net/](https://support.snowflake.net/).
The driver will try to detect automatically, whether your runtime is susceptible for this bug or not, and if so, log a message on `Warning` loglevel.

Details in [issue 773](https://github.com/snowflakedb/gosnowflake/issues/773)
9 changes: 9 additions & 0 deletions driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"database/sql"
"database/sql/driver"
"os"
"runtime"
"sync"
)

Expand Down Expand Up @@ -57,6 +58,14 @@
var logger = CreateDefaultLogger()

func init() {
if runtime.GOOS == "linux" {
// TODO: delete this once we replaced 99designs/keyring (SNOW-1017659) and/or keyring#103 is resolved
leak, logMsg := canDbusLeakProcesses()
if leak {
// 99designs/keyring#103 -> gosnowflake#773
logger.Warn(logMsg)
}

Check warning on line 67 in driver.go

View check run for this annotation

Codecov / codecov/patch

driver.go#L65-L67

Added lines #L65 - L67 were not covered by tests
}
sql.Register("snowflake", &SnowflakeDriver{})
logger.SetLogLevel("error")
if runningOnGithubAction() {
Expand Down
28 changes: 28 additions & 0 deletions util.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"io"
"math/rand"
"os"
"os/exec"
"strings"
"sync"
"time"
Expand Down Expand Up @@ -292,3 +293,30 @@
func chooseRandomFromRange(min float64, max float64) float64 {
return rand.Float64()*(max-min) + min
}

func isDbusDaemonRunning() bool {
// TODO: delete this once we replaced 99designs/keyring (SNOW-1017659) and/or keyring#103 is resolved
cmd := exec.Command("pidof", "dbus-daemon")
_, err := cmd.Output()

// false: process not running, pidof not available (sysvinit-tools, busybox, etc missing)
return err == nil

Check warning on line 303 in util.go

View check run for this annotation

Codecov / codecov/patch

util.go#L297-L303

Added lines #L297 - L303 were not covered by tests
}

func canDbusLeakProcesses() (bool, string) {
// TODO: delete this once we replaced 99designs/keyring (SNOW-1017659) and/or keyring#103 is resolved
leak := false
message := ""

valDbus, haveDbus := os.LookupEnv("DBUS_SESSION_BUS_ADDRESS")
if !haveDbus || strings.Contains(valDbus, "unix:abstract") {
// if DBUS_SESSION_BUS_ADDRESS is not set or set to an abstract socket, it's not necessarily a problem, only
sfc-gh-pfus marked this conversation as resolved.
Show resolved Hide resolved
if isDbusDaemonRunning() {
// we're probably susceptible to https://github.com/99designs/keyring/issues/103 here
leak = true
message += "DBUS_SESSION_BUS_ADDRESS envvar looks to be not set, this can lead to runaway dbus-daemon processes. " +
"To avoid this, set envvar DBUS_SESSION_BUS_ADDRESS=$XDG_RUNTIME_DIR/bus (if it exists) or DBUS_SESSION_BUS_ADDRESS=/dev/null."
}

Check warning on line 319 in util.go

View check run for this annotation

Codecov / codecov/patch

util.go#L313-L319

Added lines #L313 - L319 were not covered by tests
}
return leak, message
}