Skip to content

Commit

Permalink
Merge remote-tracking branch 'refs/remotes/origin/no_agent' into no_a…
Browse files Browse the repository at this point in the history
…gent
  • Loading branch information
Thrameos committed Nov 30, 2024
2 parents e95010f + 67f732d commit 800ce78
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 21 deletions.
23 changes: 12 additions & 11 deletions jpype/_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,6 @@ def _expandClassPath(


_JVM_started = False
_tmp = None

def interactive():
return bool(getattr(sys, 'ps1', sys.flags.interactive))
Expand All @@ -179,13 +178,13 @@ def _findTemp():
else:
dirlist.extend([ '/tmp', '/var/tmp', '/usr/tmp' ])

Check warning on line 179 in jpype/_core.py

View check run for this annotation

Codecov / codecov/patch

jpype/_core.py#L179

Added line #L179 was not covered by tests

name = str(os.getpid)
name = str(os.getpid())
for d in dirlist:
p = Path("%s/%s"%(d,name))
try:
p.touch()
p.unlink()
except Exception:
except Exception as ex:
continue
return d
raise SystemError("Unable to find non-ansii path")

Check warning on line 190 in jpype/_core.py

View check run for this annotation

Codecov / codecov/patch

jpype/_core.py#L181-L190

Added lines #L181 - L190 were not covered by tests
Expand Down Expand Up @@ -303,6 +302,7 @@ def startJVM(
java_class_path.append(support_lib)
java_class_path = list(filter(len, java_class_path))
classpath = _classpath._SEP.join(java_class_path)
tmp = None

# Make sure our module is always on the classpath
if not classpath.isascii():
Expand All @@ -314,13 +314,14 @@ def startJVM(
if not support_lib.isascii():
import tempfile
import shutil
global _tmp
_tmp = tempfile.TemporaryDirectory(dir = _findTemp())
if not _tmp.name.isascii():
raise ValueError("Unable to find ascii temp directory. Clear TEMPDIR, TEMP, and TMP environment variables")
sl2 = os.path.join(_tmp.name, "org.jpype.jar")
shutil.copyfile(support_lib, sl2)
support_lib = sl2
fd, path = tempfile.mkstemp(dir = _findTemp())
if not path.isascii():
raise ValueError("Unable to find ascii temp directory.")
shutil.copyfile(support_lib, path)
support_lib = path
tmp = path
os.close(fd)

Check warning on line 323 in jpype/_core.py

View check run for this annotation

Codecov / codecov/patch

jpype/_core.py#L315-L323

Added lines #L315 - L323 were not covered by tests
# Don't remove

# ok, setup the jpype system classloader and add to the path after startup
# this guarentees all classes have the same permissions as they did in the past
Expand All @@ -343,7 +344,7 @@ def startJVM(
prior = [locale.getlocale(i) for i in categories]
# Start the JVM
_jpype.startup(jvmpath, tuple(jvm_args + extra_jvm_args),
ignoreUnrecognized, convertStrings, interrupt)
ignoreUnrecognized, convertStrings, interrupt, tmp)
# Collect required resources for operation
initializeResources()
# Restore locale
Expand Down
47 changes: 43 additions & 4 deletions native/common/jp_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@
#include "jp_platform.h"
#include "jp_gc.h"

#ifdef WIN32
#include <Windows.h>
#else
#if defined(_HPUX) && !defined(_IA64)
#include <dl.h>
#else
#include <dlfcn.h>
#endif // HPUX
#include <errno.h>
#endif


JPResource::~JPResource() = default;


Expand Down Expand Up @@ -159,6 +171,35 @@ void JPContext::attachJVM(JNIEnv* env)
initializeResources(env, false);
}

std::string getShared()
{
#ifdef WIN32
// Windows specific
char path[MAX_PATH];
HMODULE hm = NULL;
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS |
GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR) &getShared, &hm) != 0 &&
GetModuleFileName(hm, path, sizeof(path)) != 0)
{
// This is needed when there is no-ascii characters in path
char shortPathBuffer[MAX_PATH];
GetShortPathName(path, shortPathBuffer, MAX_PATH);
return shortPathBuffer;
}
#else
// Linux specific
Dl_info info;
if (dladdr((void*)getShared, &info))
return info.dli_fname;
#endif
// Generic
JPPyObject import = JPPyObject::use(PyImport_AddModule("importlib.util"));
JPPyObject jpype = JPPyObject::call(PyObject_CallMethod(import.get(), "find_spec", "s", "_jpype"));
JPPyObject origin = JPPyObject::call(PyObject_GetAttrString(jpype.get(), "origin"));
return JPPyString::asStringUTF8(origin.get());
}

void JPContext::initializeResources(JNIEnv* env, bool interrupt)
{
JPJavaFrame frame = JPJavaFrame::external(this, env);
Expand Down Expand Up @@ -215,10 +256,8 @@ void JPContext::initializeResources(JNIEnv* env, bool interrupt)

if (!m_Embedded)
{
JPPyObject import = JPPyObject::use(PyImport_AddModule("importlib.util"));
JPPyObject jpype = JPPyObject::call(PyObject_CallMethod(import.get(), "find_spec", "s", "_jpype"));
JPPyObject origin = JPPyObject::call(PyObject_GetAttrString(jpype.get(), "origin"));
val[2].l = frame.fromStringUTF8(JPPyString::asStringUTF8(origin.get()));
std::string shared = getShared();
val[2].l = frame.fromStringUTF8(shared);
}

// Required before launch
Expand Down
32 changes: 30 additions & 2 deletions native/python/pyjp_module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@
#include "jp_gc.h"
#include "jp_stringtype.h"
#include "jp_classloader.h"
#ifdef WIN32
#include <Windows.h>
#endif

void PyJPModule_installGC(PyObject* module);

Expand Down Expand Up @@ -229,6 +232,7 @@ int PyJP_IsInstanceSingle(PyObject* obj, PyTypeObject* type)
#ifndef ANDROID
extern JNIEnv *Android_JNI_GetEnv();

static string jarTmpPath;
static PyObject* PyJPModule_startup(PyObject* module, PyObject* pyargs)
{
JP_PY_TRY("PyJPModule_startup");
Expand All @@ -238,11 +242,23 @@ static PyObject* PyJPModule_startup(PyObject* module, PyObject* pyargs)
char ignoreUnrecognized = true;
char convertStrings = false;
char interrupt = false;
PyObject* tmp;

if (!PyArg_ParseTuple(pyargs, "OO!bbb", &vmPath, &PyTuple_Type, &vmOpt,
&ignoreUnrecognized, &convertStrings, &interrupt))
if (!PyArg_ParseTuple(pyargs, "OO!bbbO", &vmPath, &PyTuple_Type, &vmOpt,
&ignoreUnrecognized, &convertStrings, &interrupt, &tmp))
return nullptr;

if (tmp != Py_None)
{
if (!(JPPyString::check(tmp)))
{
PyErr_SetString(PyExc_TypeError, "Java jar path must be a string");
return nullptr;
}
jarTmpPath = JPPyString::asStringUTF8(tmp);
}


if (!(JPPyString::check(vmPath)))
{
PyErr_SetString(PyExc_TypeError, "Java JVM path must be a string");
Expand Down Expand Up @@ -298,6 +314,18 @@ static PyObject* PyJPModule_shutdown(PyObject* obj, PyObject* pyargs, PyObject*
return nullptr;

JPContext_global->shutdownJVM(destroyJVM, freeJVM);

#ifdef WIN32
// Thus far this doesn't work on WINDOWS. The issue is a bug in the JVM
// is holding the file open and there is no apparent method to close it
// so that this can succeed
if (jarTmpPath != "")
remove(jarTmpPath.c_str());
#else
if (jarTmpPath != "")
unlink(jarTmpPath.c_str());

Check warning on line 326 in native/python/pyjp_module.cpp

View check run for this annotation

Codecov / codecov/patch

native/python/pyjp_module.cpp#L326

Added line #L326 was not covered by tests
#endif

Py_RETURN_NONE;
JP_PY_CATCH(nullptr);
}
Expand Down
10 changes: 6 additions & 4 deletions test/jpypetest/test_fault.py
Original file line number Diff line number Diff line change
Expand Up @@ -1083,13 +1083,15 @@ def testStartupBadArg(self):
with self.assertRaisesRegex(TypeError, "takes exactly"):
_jpype.startup()
with self.assertRaisesRegex(TypeError, "must be tuple"):
_jpype.startup(object(), object(), True, True, True)
_jpype.startup(object(), object(), True, True, True, None)
with self.assertRaisesRegex(TypeError, "must be strings"):
_jpype.startup("", (object(),), True, True, True)
_jpype.startup("", (object(),), True, True, True, None)
with self.assertRaisesRegex(TypeError, "must be a string"):
_jpype.startup(object(), tuple(), True, True, True)
_jpype.startup(object(), tuple(), True, True, True, None)
with self.assertRaisesRegex(TypeError, "must be a string"):
_jpype.startup("", tuple(), True, True, True, object())
with self.assertRaisesRegex(OSError, "started"):
_jpype.startup("", tuple(), True, True, True)
_jpype.startup("", tuple(), True, True, True, None)

def testGetClass(self):
with self.assertRaisesRegex(TypeError, "not found"):
Expand Down

0 comments on commit 800ce78

Please sign in to comment.