Skip to content

Commit 067b70f

Browse files
Make AbstractSession AutoCloseable (JAVA) and safer close
Enable safe automatic closing of ETP sessions and harden close semantics. - cmake/FetpapiClientUsingFesapi.java: Use try-with-resources for ClientSession so sessions are closed automatically and update messaging to reflect AutoCloseable behavior. - cmake/swigEtp1_2Include.i.in: Expose AbstractSession as java.lang.AutoCloseable via SWIG typemaps, add Java imports, implement a Java close() that calls closeAndBlock() then delete(), and add docs/nodefaultctor placement for AbstractSession. Fix #31 - src/fetpapi/etp/AbstractSession.h: Make the destructor call closeAndBlock() to ensure sockets are closed when instances are destroyed; guard close() and closeAndBlock() against repeated calls and log redundant attempts. These changes prevent resource leaks by making session lifetime management safer and allow Java callers to use try-with-resources for deterministic cleanup.
1 parent 6c9954e commit 067b70f

7 files changed

Lines changed: 189 additions & 97 deletions

File tree

.github/workflows/github-actions.yml

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,7 @@ jobs:
227227
- name: Build wheels
228228
uses: pypa/cibuildwheel@v3.2.1
229229
env:
230-
CIBW_BUILD: cp38-win_amd64 cp39-win_amd64 cp310-win_amd64 cp311-win_amd64 cp312-win_amd64 cp313-win_amd64
230+
CIBW_BUILD: cp311-win_amd64 cp312-win_amd64 cp313-win_amd64
231231
CIBW_ARCHS: auto64
232232
CIBW_BEFORE_ALL: >
233233
%VCPKG_INSTALLATION_ROOT%\vcpkg install boost-uuid minizip hdf5[zlib] &&
@@ -238,7 +238,7 @@ jobs:
238238
cmake -DCMAKE_TOOLCHAIN_FILE=%VCPKG_INSTALLATION_ROOT%\scripts\buildsystems\vcpkg.cmake -G"Visual Studio 17 2022" -A x64 -T host=x64 -Wno-dev -Wno-deprecated -DCMAKE_INSTALL_PREFIX=${{ runner.temp }}/fesapi-install ${{ runner.temp }}\fesapi-src &&
239239
cmake --build . --config Release -j2 &&
240240
cmake --build . --config Release --target INSTALL &&
241-
%VCPKG_INSTALLATION_ROOT%\vcpkg install bext-wintls boost-beast boost-url avro-cpp &&
241+
%VCPKG_INSTALLATION_ROOT%\vcpkg install bext-wintls boost-beast boost-url boost-stacktrace avro-cpp &&
242242
cd ${{ runner.temp }} &&
243243
mkdir fetpapi-build &&
244244
cd fetpapi-build &&
@@ -269,7 +269,7 @@ jobs:
269269
uses: pypa/cibuildwheel@v3.2.1
270270
# RedHat nor Debian maintain security patches for hdf5. We consequently build the latest HDF5 version.
271271
env:
272-
CIBW_BUILD: cp38-manylinux_* cp39-manylinux_* cp310-manylinux_* cp311-manylinux_* cp312-manylinux_* cp313-manylinux_*
272+
CIBW_BUILD: cp310-manylinux_* cp311-manylinux_* cp312-manylinux_* cp313-manylinux_*
273273
CIBW_ARCHS: auto64
274274
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
275275
CIBW_BEFORE_ALL: >
@@ -307,8 +307,68 @@ jobs:
307307
cmake3 --build . -j2 &&
308308
cmake3 --install .
309309
CIBW_REPAIR_WHEEL_COMMAND_LINUX: >
310-
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/fesapi-install/lib64:/fetpapi-install/lib64 &&
311-
auditwheel repair -w {dest_dir} {wheel}
310+
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/fetpapi-install/lib64 &&
311+
auditwheel repair -w {dest_dir} {wheel} --exclude libFesapiCpp.so &&
312+
pip install consolidatewheels &&
313+
pip download fesapi --no-deps --only-binary=:all: &&
314+
consolidatewheels $(echo {wheel} | sed 's/fetpapi-0.6.0/fesapi-2.14.1/g') {wheel} --dest=.
315+
CIBW_TEST_COMMAND: python {project}/python/example/etp_client_example.py
316+
with:
317+
package-dir: ./python
318+
output-dir: wheelhouse
319+
- uses: actions/upload-artifact@v4
320+
with:
321+
name: cibw-wheels-manylinux_2_28
322+
path: ./wheelhouse/*.whl
323+
build_wheels_linux2:
324+
name: Build wheels on ubuntu-latest2
325+
runs-on: ubuntu-latest
326+
steps:
327+
- uses: actions/checkout@v5
328+
- name: Stub `setup.py` check
329+
# It will be generated during CMake run
330+
# https://github.com/pypa/cibuildwheel/issues/1139
331+
run: touch python/setup.py
332+
- name: Build wheels
333+
uses: pypa/cibuildwheel@v3.2.1
334+
# RedHat nor Debian maintain security patches for hdf5. We consequently build the latest HDF5 version.
335+
env:
336+
CIBW_BUILD: cp310-manylinux_* cp311-manylinux_* cp312-manylinux_* cp313-manylinux_*
337+
CIBW_ARCHS: auto64
338+
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
339+
CIBW_BEFORE_ALL: |
340+
yum install -y wget gcc-c++ boost-devel openssl-devel
341+
yum search epel-release
342+
yum info epel-release
343+
yum install -y epel-release
344+
yum --enablerepo=epel install -y minizip1.2-devel hdf5-devel cmake3
345+
cd /
346+
git clone --branch v2.14.1.0 --single-branch https://github.com/F2I-Consulting/fesapi.git /fesapi-src
347+
mkdir fesapi-build
348+
cd fesapi-build
349+
cmake3 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX:STRING=/fesapi-install /fesapi-src
350+
mv /fesapi-src/src /fesapi-src/fesapi
351+
pip download fesapi --no-deps --only-binary=:all: --no-cache-dir --no-color
352+
FESAPI_WHEEL=$(ls fesapi-*.whl | head -n 1)
353+
unzip "$FESAPI_WHEEL"
354+
LIB_FESAPI_CPP=$(find "$(pwd)/fesapi.libs" -name 'libFesapiCpp*' -type f | head -n 1)
355+
echo "Found libFesapiCpp file: $LIB_FESAPI_CPP"
356+
cd /
357+
git clone -b release-1.12.1 https://github.com/apache/avro.git avro
358+
mkdir avro-build
359+
cd avro-build
360+
cmake3 -Wno-dev -Wno-deprecated -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release -DAVRO_BUILD_EXECUTABLES=FALSE -DAVRO_BUILD_TESTS=FALSE -DAVRO_BUILD_SHARED=FALSE -DCMAKE_INSTALL_PREFIX=/avro-install /avro/lang/c++
361+
cmake3 --build . -j2
362+
cmake3 --install .
363+
cd /
364+
mkdir build
365+
cd build
366+
cmake3 -DCMAKE_BUILD_TYPE=Release -DAVRO_ROOT=/avro-install -DAVRO_USE_STATIC_LIBS=TRUE -DWITH_FESAPI=TRUE -DFESAPI_INCLUDE_DIR=/fesapi-src -DFESAPI_LIBRARY_RELEASE="$LIB_FESAPI_CPP" -DWITH_PYTHON_WRAPPING=TRUE -DCMAKE_INSTALL_PREFIX:STRING=/fetpapi-install {project}
367+
cmake3 --build . -j2
368+
cmake3 --install .
369+
CIBW_REPAIR_WHEEL_COMMAND_LINUX: >
370+
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/fesapi-build/fesapi.libs:/fetpapi-install/lib64 &&
371+
auditwheel repair -w {dest_dir} {wheel} --exclude "$LIB_FESAPI_CPP"
312372
CIBW_TEST_COMMAND: python {project}/python/example/etp_client_example.py
313373
with:
314374
package-dir: ./python
@@ -329,7 +389,7 @@ jobs:
329389
- name: Build wheels
330390
uses: pypa/cibuildwheel@v3.2.1
331391
env:
332-
CIBW_BUILD: cp38-macosx_* cp39-macosx_* cp310-macosx_* cp311-macosx_* cp312-macosx_* cp313-macosx_*
392+
CIBW_BUILD: cp310-macosx_* cp311-macosx_* cp312-macosx_* cp313-macosx_*
333393
CIBW_ARCHS: auto64
334394
# See https://cibuildwheel.pypa.io/en/stable/cpp_standards/#macos-and-deployment-target-versions
335395
MACOSX_DEPLOYMENT_TARGET: 11.0

cmake/FetpapiClientUsingFesapi.java

Lines changed: 74 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -101,84 +101,83 @@ public static void main(String[] args) {
101101
additionalHeaderField.put("data-partition-id", "osdu"); // Example for OSDU RDDMS
102102
initializationParams.setAdditionalHandshakeHeaderFields(additionalHeaderField);
103103

104-
ClientSession clientSession = fetpapi.createClientSession(initializationParams, authorization);
105-
clientSession.setCoreProtocolHandlers(new CoreHandlers(clientSession));
106-
clientSession.setDataspaceProtocolHandlers(new DataspaceHandlers(clientSession));
107-
clientSession.setDiscoveryProtocolHandlers(new DiscoveryHandlers(clientSession));
108-
clientSession.setStoreProtocolHandlers(new StoreHandlers(clientSession));
109-
clientSession.setDataArrayProtocolHandlers(new DataArrayHandlers(clientSession));
110-
new Thread(clientSession::run).start();
111-
long start = System.currentTimeMillis();
112-
while (clientSession.isEtpSessionClosed() && System.currentTimeMillis() - start < 5000) {
113-
TimeUnit.MILLISECONDS.sleep(1);
114-
}
115-
if (clientSession.isEtpSessionClosed()) {
116-
System.err.println("The ETP session cound not be establisehd in 5 seconds.");
117-
return;
118-
}
119-
System.out.println("Now connected to ETP Server");
120-
// ****** We are now connected to ETP server through clientSession ******
121-
// Set the HDF proxy factory in order to use one compliant with ETP
122-
repo.setHdfProxyFactory(new FesapiHdfProxyFactory(clientSession));
123-
124-
// ****** Get a dataspace content. This corresponds to getting the content of an EPC file ******
125-
// Find an available ETP dataspace
126-
DataspaceVector allDataspaces = clientSession.getDataspaces();
127-
Optional<Dataspace> dataspace = allDataspaces.stream().findAny();
128-
if (dataspace.isEmpty()) {
129-
clientSession.close();
130-
System.err.println("The ETP server has no dataspace.");
131-
return;
132-
}
133-
System.out.println("Working on dataspace " + dataspace.get().getUri());
134-
// List resources of this ETP dataspace
135-
ContextInfo etpContext = new ContextInfo();
136-
etpContext.setUri(dataspace.get().getUri());
137-
etpContext.setDepth(1);
138-
ResourceVector allResources = clientSession.getResources(etpContext, ContextScopeKind.self);
139-
if (allResources.isEmpty()) {
140-
clientSession.close();
141-
System.err.println("The ETP dataspace has no resource.");
142-
return;
143-
}
144-
// Get dataobjects from the resources to the DataObjectRepository
145-
MapStringString uriMap = new MapStringString();
146-
long index = 0;
147-
for (Resource resource : allResources) {
148-
uriMap.put(Long.toString(index++), resource.getUri());
149-
}
150-
MapStringDataObject allDataObjects = clientSession.getDataObjects(uriMap);
151-
for (DataObject dataObject : allDataObjects.values()) {
152-
repo.addOrReplaceGsoapProxy(dataObject.getData(), fetpapi.getDataObjectType(dataObject.getResource().getUri()), fetpapi.getDataspaceUri(dataObject.getResource().getUri()));
153-
}
154-
// ****** We have now in the DataObjectRepository the same content as if we would have deserialized and EPC file looking like the dataspace ******
155-
156-
// ****** Use the DataObjectRepository exactly as you are used to do with FESAPI ******
157-
if (repo.getIjkGridRepresentationCount() > 0) {
158-
IjkGridExplicitRepresentation ijkGrid = repo.getIjkGridExplicitRepresentation(0);
159-
ijkGrid.loadSplitInformation();
160-
long originIndex = ijkGrid.getXyzPointIndexFromCellCorner(0, 0, 0, 0);
161-
System.out.println("The index of the grid origin in XYZ points is : " + originIndex);
162-
ijkGrid.unloadSplitInformation();
163-
if (ijkGrid.getValuesPropertyCount() > 0) {
164-
AbstractValuesProperty prop = ijkGrid.getValuesProperty(0);
165-
SWIGTYPE_p_double propValues = fesapi.new_DoubleArray(prop.getValuesCountOfPatch(0));
166-
try {
167-
prop.getDoubleValuesOfPatch(0, propValues);
168-
System.out.println("The first cell value of prop " + prop.getTitle() + " is " + fesapi.DoubleArray_getitem(propValues, 0));
169-
}
170-
finally {
171-
fesapi.delete_DoubleArray(propValues);
104+
try (ClientSession clientSession = fetpapi.createClientSession(initializationParams, authorization)) {
105+
clientSession.setCoreProtocolHandlers(new CoreHandlers(clientSession));
106+
clientSession.setDataspaceProtocolHandlers(new DataspaceHandlers(clientSession));
107+
clientSession.setDiscoveryProtocolHandlers(new DiscoveryHandlers(clientSession));
108+
clientSession.setStoreProtocolHandlers(new StoreHandlers(clientSession));
109+
clientSession.setDataArrayProtocolHandlers(new DataArrayHandlers(clientSession));
110+
new Thread(clientSession::run).start();
111+
long start = System.currentTimeMillis();
112+
while (clientSession.isEtpSessionClosed() && System.currentTimeMillis() - start < 5000) {
113+
TimeUnit.MILLISECONDS.sleep(1);
114+
}
115+
if (clientSession.isEtpSessionClosed()) {
116+
System.err.println("The ETP session cound not be establisehd in 5 seconds.");
117+
return;
118+
}
119+
System.out.println("Now connected to ETP Server");
120+
// ****** We are now connected to ETP server through clientSession ******
121+
// Set the HDF proxy factory in order to use one compliant with ETP
122+
repo.setHdfProxyFactory(new FesapiHdfProxyFactory(clientSession));
123+
124+
// ****** Get a dataspace content. This corresponds to getting the content of an EPC file ******
125+
// Find an available ETP dataspace
126+
DataspaceVector allDataspaces = clientSession.getDataspaces();
127+
Optional<Dataspace> dataspace = allDataspaces.stream().findAny();
128+
if (dataspace.isEmpty()) {
129+
clientSession.close();
130+
System.err.println("The ETP server has no dataspace.");
131+
return;
132+
}
133+
System.out.println("Working on dataspace " + dataspace.get().getUri());
134+
// List resources of this ETP dataspace
135+
ContextInfo etpContext = new ContextInfo();
136+
etpContext.setUri(dataspace.get().getUri());
137+
etpContext.setDepth(1);
138+
ResourceVector allResources = clientSession.getResources(etpContext, ContextScopeKind.self);
139+
if (allResources.isEmpty()) {
140+
clientSession.close();
141+
System.err.println("The ETP dataspace has no resource.");
142+
return;
143+
}
144+
// Get dataobjects from the resources to the DataObjectRepository
145+
MapStringString uriMap = new MapStringString();
146+
long index = 0;
147+
for (Resource resource : allResources) {
148+
uriMap.put(Long.toString(index++), resource.getUri());
149+
}
150+
MapStringDataObject allDataObjects = clientSession.getDataObjects(uriMap);
151+
for (DataObject dataObject : allDataObjects.values()) {
152+
repo.addOrReplaceGsoapProxy(dataObject.getData(), fetpapi.getDataObjectType(dataObject.getResource().getUri()), fetpapi.getDataspaceUri(dataObject.getResource().getUri()));
153+
}
154+
// ****** We have now in the DataObjectRepository the same content as if we would have deserialized and EPC file looking like the dataspace ******
155+
156+
// ****** Use the DataObjectRepository exactly as you are used to do with FESAPI ******
157+
if (repo.getIjkGridExplicitRepresentationCount() > 0) {
158+
IjkGridExplicitRepresentation ijkGrid = repo.getIjkGridExplicitRepresentation(0);
159+
ijkGrid.loadSplitInformation();
160+
long originIndex = ijkGrid.getXyzPointIndexFromCellCorner(0, 0, 0, 0);
161+
System.out.println("The index of the grid origin in XYZ points is : " + originIndex);
162+
ijkGrid.unloadSplitInformation();
163+
if (ijkGrid.getValuesPropertyCount() > 0) {
164+
AbstractValuesProperty prop = ijkGrid.getValuesProperty(0);
165+
SWIGTYPE_p_double propValues = fesapi.new_DoubleArray(prop.getValuesCountOfPatch(0));
166+
try {
167+
prop.getDoubleValuesOfPatch(0, propValues);
168+
System.out.println("The first cell value of prop " + prop.getTitle() + " is " + fesapi.DoubleArray_getitem(propValues, 0));
169+
}
170+
finally {
171+
fesapi.delete_DoubleArray(propValues);
172+
}
172173
}
173174
}
175+
else {
176+
System.out.println("This dataspace has no IJK Grid");
177+
}
178+
179+
System.out.println("Closing the session thanks to AutoCloseable...");
174180
}
175-
else {
176-
System.out.println("This dataspace has no IJK Grid");
177-
}
178-
179-
// Do not forget to close session once you have processed all the dataobject repository.
180-
System.out.println("Closing the session...");
181-
clientSession.close();
182181
} catch (InterruptedException e) {
183182
e.printStackTrace();
184183
}

cmake/pyproject.toml.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ issues = "https://github.com/F2I-Consulting/fetpapi/issues"
5656
packages=['fetpapi']
5757
package-dir={"fetpapi" = "fetpapi"}
5858
ext-modules = [
59-
{name='fetpapi._fetpapi', sources=['swigGeneratedPythonWrapper.cpp'], include-dirs=['${Boost_INCLUDE_DIR}','${AVRO_INCLUDE_DIR}'${FESAPI_INCLUDE_DIR_FOR_SETUP_PY}], library-dirs=['${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}'${AVRO_LIBRARY_DIR_RELEASE}${Boost_LIBRARY_DIR_RELEASE}${FESAPI_LIBRARY_DIR_RELEASE}], libraries=['${ASSEMBLY_NAME}'${AVRO_LIBRARY_RELEASE_WLE}${Boost_LIBRARY_RELEASE_WLE}${FESAPI_LIBRARY_RELEASE_WLE}], ${EXTRA_COMPILE_ARGS}}
59+
{name='fetpapi._fetpapi', sources=['swigGeneratedPythonWrapper.cpp'], include-dirs=['${Boost_INCLUDE_DIR}','${AVRO_INCLUDE_DIR}'${FESAPI_INCLUDE_DIR_FOR_SETUP_PY}], library-dirs=['${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}'${AVRO_LIBRARY_DIR_RELEASE}${Boost_LIBRARY_DIR_RELEASE}${FESAPI_LIBRARY_DIR_RELEASE}], libraries=['${ASSEMBLY_NAME}'${AVRO_LIBRARY_RELEASE_WLE}${Boost_LIBRARY_RELEASE_WLE}], ${EXTRA_COMPILE_ARGS}}
6060
]
6161

6262
[tool.setuptools.package-data]

cmake/swigEtp1_2Include.i.in

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,6 +1404,11 @@ namespace Energistics {
14041404
#endif
14051405

14061406
#ifdef SWIGJAVA
1407+
%typemap(javaimports) ETP_NS::AbstractSession %{
1408+
import java.lang.AutoCloseable;
1409+
import com.f2i_consulting.fetpapi.*;
1410+
%}
1411+
%typemap(javainterfaces) ETP_NS::AbstractSession "AutoCloseable"
14071412
%typemap(javacode) ETP_NS::AbstractSession %{
14081413
private CoreHandlers coreHandlersReference;
14091414
private DiscoveryHandlers discoveryHandlersReference;
@@ -1414,6 +1419,12 @@ namespace Energistics {
14141419
private TransactionHandlers transactionHandlersReference;
14151420
private DataspaceHandlers dataspaceHandlersReference;
14161421
private DataspaceOSDUHandlers dataspaceOSDUHandlersReference;
1422+
1423+
@Override
1424+
public void close() {
1425+
closeAndBlock();
1426+
delete();
1427+
}
14171428
%}
14181429

14191430
%typemap(javain,
@@ -1640,8 +1651,12 @@ namespace ETP_NS
16401651
virtual void on_CopyToDataspace(const Energistics::Etp::v12::Protocol::DataspaceOSDU::CopyToDataspace& msg, int64_t correlationId);
16411652
virtual void on_CopyToDataspaceResponse(const Energistics::Etp::v12::Protocol::DataspaceOSDU::CopyToDataspaceResponse & msg, int64_t correlationId);
16421653
};
1643-
1654+
16441655
%nodefaultctor AbstractSession;
1656+
/**
1657+
* The most abstract class defining a websocket ETP session.
1658+
* When such an instance is deleted, this class ensures that the socket is closed.
1659+
*/
16451660
class AbstractSession
16461661
{
16471662
public:
@@ -1722,13 +1737,6 @@ namespace ETP_NS
17221737
/****************
17231738
***** CORE ******
17241739
****************/
1725-
1726-
/**
1727-
* Send a message for closing to the server after having sent all previous messages.
1728-
* The session would really close only after all messages have been sent and responded.
1729-
* This method does not block.
1730-
*/
1731-
void close();
17321740

17331741
/**
17341742
* Send a message for closing to the server after having sent all previous messages.

python/CMakeLists.txt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ if (WITH_FESAPI)
5656
string(REGEX REPLACE "^lib" "" FESAPI_LIBRARY_RELEASE_WLE ${FESAPI_LIBRARY_RELEASE_WLE})
5757
endif()
5858
set (FESAPI_LIBRARY_RELEASE_WLE ",'${FESAPI_LIBRARY_RELEASE_WLE}'")
59+
get_filename_component(FESAPI_LIBRARY_RELEASE_NAME ${FESAPI_LIBRARY_RELEASE} NAME)
5960
endif ()
6061
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
61-
set (EXTRA_COMPILE_ARGS "extra-compile-args=['/DSWIG_TYPE_TABLE=FESTAPI', '/std:c++17', '/utf-8']")
62+
set (EXTRA_COMPILE_ARGS "extra-compile-args=['-l:${FESAPI_LIBRARY_RELEASE}', '/DSWIG_TYPE_TABLE=FESTAPI', '/std:c++17', '/utf-8']")
6263
else ()
63-
set (EXTRA_COMPILE_ARGS "extra-compile-args=['-DSWIG_TYPE_TABLE=FESTAPI', '-std=c++17']")
64+
set (EXTRA_COMPILE_ARGS "extra-compile-args=['-l:${FESAPI_LIBRARY_RELEASE}', '-DSWIG_TYPE_TABLE=FESTAPI', '-std=c++17']")
6465
endif()
6566
configure_file(${CMAKE_SOURCE_DIR}/cmake/pyproject.toml.in ${CMAKE_SOURCE_DIR}/python/pyproject.toml) # Overwrite if different
6667

python/example/etp_client_example.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ def start_etp_server(client_session):
1919
initialization_params.setAdditionalHandshakeHeaderFields(additionalHeaderField)
2020

2121
print("Creating the session...")
22+
global client_session
2223
client_session = fetpapi.createClientSession(initialization_params, authorization)
23-
t = Thread(target=start_etp_server, args=(client_session,), daemon=True)
24+
t = Thread(target=start_etp_server, args=(client_session,), daemon=False)
2425
print("Trying to connect to " + etp_server_url + " ...")
2526
t.start()
2627
start_time = perf_counter()
@@ -130,5 +131,7 @@ def start_etp_server(client_session):
130131
print("This dataspace has no 2d Grid")
131132

132133
repo.clear()
133-
client_session.close()
134-
print("FINISHED")
134+
print("Closing the session...");
135+
client_session.closeAndBlock()
136+
t.join(timeout=10) # Wait for the thread to finish with a timeout
137+
print("The session is now closed.")

0 commit comments

Comments
 (0)