Skip to content

Commit

Permalink
Add (primitive) version of SIGTERM handling to jpype (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
dfangl authored Nov 21, 2024
1 parent 29cce31 commit 44035ee
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 23 deletions.
85 changes: 85 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Build

on:
push:
branches:
- main
tags:
- v*.*
pull_request:
workflow_dispatch:


jobs:
build_wheels:
runs-on: ubuntu-latest
strategy:
matrix:
# macos-13 is an intel runner, macos-14 is apple silicon
pyver: [ cp311, cp312 ]
steps:
- name: Checkout
uses: actions/checkout@v4

# Used to host cibuildwheel
- name: Setup python
uses: actions/setup-python@v5

- name: Set up QEMU
if: runner.os == 'Linux'
uses: docker/setup-qemu-action@v3
with:
platforms: all

- name: Build wheels
uses: pypa/[email protected]
env:
# configure cibuildwheel to build native archs ('auto'), and some
# emulated ones
CIBW_BUILD: ${{matrix.pyver}}-*
CIBW_ARCHS_LINUX: auto aarch64
CIBW_BEFORE_ALL_LINUX: >
yum install -y java-11-openjdk-devel
CIBW_SKIP: '*-musllinux_*'

- uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.pyver }}
path: ./wheelhouse/*.whl

build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Build sdist
run: pipx run build --sdist

- uses: actions/upload-artifact@v4
with:
name: cibw-sdist
path: dist/*.tar.gz

upload_pypi:
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
environment:
name: pypi
url: https://pypi.org/p/jpype1-ext
permissions:
id-token: write
# if: github.event_name == 'release' && github.event.action == 'published'
# or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this)
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
steps:
- uses: actions/download-artifact@v4
with:
# unpacks all CIBW artifacts into dist/
pattern: cibw-*
path: dist
merge-multiple: true
- name: List artifacts
run: ls -lah dist/
- name: Publish package distributions to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,4 @@ jacoco/
wheelhouse/
vc*.pdb
*.class
.venv
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ JPype

|implementation| |pyversions| |javaversions| |jvm| |platform| |license|

Why this fork for LocalStack?
--------------
We forked the jpype project to add a SIGTERM signal handler to be used in `LocalStack <https://github.com/localstack/localstack>`
We plan on contributing the changes upstream, should they be accepted.

JPype is a Python module to provide full access to Java from
within Python. It allows Python to make use of Java only libraries,
exploring and visualization of Java structures, development and testing
Expand Down
4 changes: 2 additions & 2 deletions native/common/jp_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,10 +446,10 @@ extern "C" JNIEXPORT void JNICALL Java_org_jpype_JPypeContext_onShutdown

static int interruptState = 0;
extern "C" JNIEXPORT void JNICALL Java_org_jpype_JPypeSignal_interruptPy
(JNIEnv *env, jclass cls)
(JNIEnv *env, jclass cls, jint signal)
{
interruptState = 1;
PyErr_SetInterrupt();
PyErr_SetInterruptEx((int) signal);
}

extern "C" JNIEXPORT void JNICALL Java_org_jpype_JPypeSignal_acknowledgePy
Expand Down
33 changes: 16 additions & 17 deletions native/java/org/jpype/JPypeSignal.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
**************************************************************************** */
package org.jpype;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
Expand All @@ -31,6 +30,17 @@ public class JPypeSignal

static Thread main;

static Object getSignalHandler(Class signalHandlerClazz, int signal) throws ClassNotFoundException {
return Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]
{
signalHandlerClazz
}, (proxy, method, args) -> {
main.interrupt();
interruptPy(signal);
return null;
});
}

static void installHandlers()
{
try
Expand All @@ -39,28 +49,17 @@ static void installHandlers()
Class SignalHandler = Class.forName("sun.misc.SignalHandler");
main = Thread.currentThread();
Method method = Signal.getMethod("handle", Signal, SignalHandler);

Object handler = Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]
{
SignalHandler
}, new InvocationHandler()
{
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
main.interrupt();
interruptPy();
return null;
}
});
Object intr = Signal.getDeclaredConstructor(String.class).newInstance("INT");
method.invoke(null, intr, handler);
method.invoke(null, intr, getSignalHandler(SignalHandler, 2));
Object intrTerm = Signal.getDeclaredConstructor(String.class).newInstance("TERM");
method.invoke(null, intrTerm, getSignalHandler(SignalHandler, 15));
} catch (InvocationTargetException | IllegalArgumentException | IllegalAccessException | InstantiationException | ClassNotFoundException | NoSuchMethodException | SecurityException ex)
{
// If we don't get the signal handler run without it. (ANDROID)
}
}

native static void interruptPy();
native static void interruptPy(int signal);

native static void acknowledgePy();
}
9 changes: 5 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ build-backend = "setuptools.build_meta"


[project]
name = "jpype1"
version = '1.5.2.dev0'
name = "jpype1-ext"
version = '0.0.2'
authors = [
{name = "Steve Menard", email = "[email protected]"},
]
maintainers = [
{name = "Luis Nell", email = "[email protected]"},
{name = "LocalStack Contributors", email = "[email protected]"},
]
description = "A Python to Java bridge"
description = "A Python to Java bridge - ext"
readme = "README.rst"
requires-python = ">=3.8"
license = {text = "License :: OSI Approved :: Apache Software License"}
Expand Down Expand Up @@ -52,7 +53,7 @@ tests = [


[project.urls]
homepage = "https://github.com/jpype-project/jpype"
homepage = "https://github.com/localstack/jpype"


[[tool.mypy.overrides]]
Expand Down

0 comments on commit 44035ee

Please sign in to comment.