Skip to content

Commit

Permalink
Merge pull request apple#75 from dreness/master
Browse files Browse the repository at this point in the history
Integrate fix from behackett, and additional tests
  • Loading branch information
dreness authored Apr 11, 2019
2 parents 133299a + 839016e commit 51a4c34
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .travis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -158,4 +158,4 @@ echo "Pip Version: $(pip$PY_MAJOR --version)"
echo "Pip packages: $(pip$PY_MAJOR list)"

echo "Running Python tests"
python$PY_MAJOR -m pytest
python$PY_MAJOR -m pytest -v
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ matrix:
include:
- env: PYENV=2.6
- env: PYENV=2.7.13
- env: PYENV=3.3.6
- env: PYENV=3.4.6
- env: PYENV=3.5.3
- env: PYENV=3.6.1
- env: PYENV=3.7.0

script:
- >
Expand Down
1 change: 1 addition & 0 deletions requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pytest
requests
psutil
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

project_name = "kerberos"

version_string = "1.3.0"
version_string = "1.3.1"

description = "Kerberos high-level interface"

Expand Down
14 changes: 12 additions & 2 deletions src/kerberos.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,10 @@ static PyObject* authGSSClientInit(PyObject* self, PyObject* args, PyObject* key
return NULL;
}
pystate = PyCObject_FromVoidPtr(state, &destroy_gss_client);
if (pystate == NULL) {
free(state);
return NULL;
}

if (pydelegatestate != NULL && PyCObject_Check(pydelegatestate)) {
delegatestate = (gss_server_state*)PyCObject_AsVoidPtr(pydelegatestate);
Expand All @@ -191,10 +195,11 @@ static PyObject* authGSSClientInit(PyObject* self, PyObject* args, PyObject* key
);

if (result == AUTH_GSS_ERROR) {
Py_DECREF(pystate);
return NULL;
}

return Py_BuildValue("(iO)", result, pystate);
return Py_BuildValue("(iN)", result, pystate);
}

static PyObject *authGSSClientClean(PyObject *self, PyObject *args)
Expand Down Expand Up @@ -530,14 +535,19 @@ static PyObject *authGSSServerInit(PyObject *self, PyObject *args)
return NULL;
}
pystate = PyCObject_FromVoidPtr(state, &destroy_gss_server);
if (pystate == NULL) {
free(state);
return NULL;
}

result = authenticate_gss_server_init(service, state);

if (result == AUTH_GSS_ERROR) {
Py_DECREF(pystate);
return NULL;
}

return Py_BuildValue("(iO)", result, pystate);
return Py_BuildValue("(iN)", result, pystate);
}

static PyObject *authGSSServerClean(PyObject *self, PyObject *args)
Expand Down
78 changes: 78 additions & 0 deletions tests/test_kerberos.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import kerberos
import os
import requests
import sys
import pytest

username = os.environ.get('KERBEROS_USERNAME', 'administrator')
password = os.environ.get('KERBEROS_PASSWORD', 'Password01')
Expand Down Expand Up @@ -108,3 +110,79 @@ def test_http_endpoint():

# Cleanup any objects still stored in memory
kerberos.authGSSClientClean(vc)


def test_leaks_server_linux():
# The method used here to check for file descriptor leaks is specific to Linux
if "linux" not in sys.platform:
pytest.skip("This test requires linux.")

import gc

SERVICE = "HTTP@%s" % hostname
COUNT = 10

def server_init():
kerberos.authGSSServerInit(SERVICE)

# Use xrange instead of range in python2
if sys.version_info[0] > 2:
for _ in range(COUNT):
server_init()
else:
for _ in xrange(COUNT):
server_init()

# Because I'm not entirely certain that python's gc guarantees timeliness
# of destructors, lets kick off a manual gc.
gc.collect()

# If we're leaking FDs, we would expect some leftover FDs with targets like:
# /var/tmp/HTTP_0
# In the clean case, the only FDs still around after a garbage collect are pipes.
dirname = os.path.join('/proc/', str(os.getpid()), 'fd')
for fname in os.listdir(dirname):
try:
target = os.readlink(os.path.join(dirname, fname))
print("fd {} => {}".format(fname, target))
assert "HTTP" not in target, "Leaking file descriptors!"
except EnvironmentError:
pass
# raw_input("Hit [ENTER] to continue> ")


def test_leaks_client():
import gc
import psutil

SERVICE = "HTTP@%s" % hostname

def client_init():
kerberos.authGSSClientInit(SERVICE)


def n_times(count):
before = psutil.Process().memory_info().rss

# Use xrange instead of range in python2
if sys.version_info[0] > 2:
for _ in range(count):
client_init()
else:
for _ in xrange(count):
client_init()

# Because I'm not entirely certain that python's gc guarantees timeliness
# of destructors, lets kick off a manual gc.
gc.collect()
after = psutil.Process().memory_info().rss
delta = after - before
print("Leaked {} total in {} calls: ~{} bytes per call".format(delta, count, delta / count))
assert delta == 0, "Leaking!"


n_times(1000)
n_times(10000)
n_times(100000)
n_times(1000000)

0 comments on commit 51a4c34

Please sign in to comment.