Skip to content

Commit

Permalink
refs #4228 fixed handling Qore program destruction in a foreign threa…
Browse files Browse the repository at this point in the history
…d in a binary module that could cause a crash (#4229)
  • Loading branch information
davidnich committed May 1, 2021
1 parent a8cae6c commit 2b72a2f
Show file tree
Hide file tree
Showing 9 changed files with 121 additions and 100 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Expand Up @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12)
# NOTE: Qore should always use semantic versioning: https://semver.org/
set(VERSION_MAJOR 0)
set(VERSION_MINOR 9)
set(VERSION_SUB 14)
set(VERSION_SUB 15)
#set(VERSION_PATCH 0)

# support <pkg>_ROOT in find_package
Expand Down Expand Up @@ -681,7 +681,7 @@ if (APPLE)
set_target_properties(libqore PROPERTIES SOVERSION 6)
set_target_properties(libqore PROPERTIES INSTALL_NAME_DIR ${CMAKE_INSTALL_FULL_LIBDIR})
else (APPLE)
set_target_properties(libqore PROPERTIES VERSION 6.3.4)
set_target_properties(libqore PROPERTIES VERSION 6.3.5)
set_target_properties(libqore PROPERTIES SOVERSION 6)
endif (APPLE)

Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Expand Up @@ -2,7 +2,7 @@

# AC_PREREQ(2.59)
# NOTE: Qore should always use semantic versioning: https://semver.org/
AC_INIT([qore], [0.9.14],
AC_INIT([qore], [0.9.15],
[David Nichols <david@qore.org>],
[qore])
AM_INIT_AUTOMAKE([no-dist-gzip dist-bzip2 tar-ustar subdir-objects])
Expand Down
9 changes: 9 additions & 0 deletions doxygen/lang/900_release_notes.dox.tmpl
Expand Up @@ -2,6 +2,15 @@

@tableofcontents

@section qore_0915 Qore 0.9.15

@par Release Summary
Bugfix release; see below for more information

@subsection qore_0915_bug_fixes Bug Fixes in Qore
- fixed handling %Qore program destruction in a foreign thread in a binary module that could cause a crash
(<a href="https://github.com/qorelanguage/qore/issues/4228">issue 4228</a>)

@section qore_0914 Qore 0.9.14

@par Release Summary
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile.am
Expand Up @@ -11,7 +11,7 @@ dummy:
echo "Build started!"

EXTRA_INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir)/lib
libqore_la_LDFLAGS = -version-info 9:4:3 -no-undefined ${QORE_LIB_LDFLAGS}
libqore_la_LDFLAGS = -version-info 9:5:3 -no-undefined ${QORE_LIB_LDFLAGS}
AM_CPPFLAGS = $(EXTRA_INCLUDES) ${QORE_LIB_CPPFLAGS}
AM_CXXFLAGS = ${QORE_LIB_CXXFLAGS}
AM_YFLAGS = -d
Expand Down
60 changes: 32 additions & 28 deletions lib/QoreProgramHelper.cpp
@@ -1,33 +1,33 @@
/*
QoreProgramHelper.cpp
QoreProgramHelper.cpp
QoreProgramHelper QoreObject Definition
QoreProgramHelper QoreObject Definition
Qore Programming Language
Qore Programming Language
Copyright (C) 2003 - 2015 David Nichols
Copyright (C) 2003 - 2021 David Nichols
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
Note that the Qore library is released under a choice of three open-source
licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
information.
Note that the Qore library is released under a choice of three open-source
licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
information.
*/

#include <qore/Qore.h>
Expand All @@ -44,18 +44,22 @@ QoreProgramHelper::QoreProgramHelper(int64 parse_options, ExceptionSink& xs) : p
/** QoreProgram objects are deleted when there reference count reaches 0.
*/
QoreProgramHelper::~QoreProgramHelper() {
// waits for all background threads to execute
thread_counter.waitForZero(&xsink);
// waits for the current Program to terminate
pgm->waitForTerminationAndDeref(&xsink);
// waits for all background threads to execute
thread_counter.waitForZero(&xsink);

// issue #4228: ensure we are running in a qore thread
QoreForeignThreadHelper qfth;

// waits for the current Program to terminate
pgm->waitForTerminationAndDeref(&xsink);
}

//! returns the QoreProgram object being managed
QoreProgram* QoreProgramHelper::operator->() {
return pgm;
return pgm;
}

//! returns the QoreProgram object being managed
QoreProgram* QoreProgramHelper::operator*() {
return pgm;
return pgm;
}
126 changes: 63 additions & 63 deletions lib/thread.cpp
Expand Up @@ -1026,140 +1026,140 @@ std::string parse_pop_name() {
}

void set_thread_resource(AbstractThreadResource* atr) {
ThreadData* td = thread_data.get();
td->trlist->set(atr);
ThreadData* td = thread_data.get();
td->trlist->set(atr);
}

int remove_thread_resource(AbstractThreadResource* atr) {
ThreadData* td = thread_data.get();
return td->trlist->remove(atr);
ThreadData* td = thread_data.get();
return td->trlist->remove(atr);
}

bool check_thread_resource(AbstractThreadResource* atr) {
ThreadData* td = thread_data.get();
return td->trlist->check(atr);
ThreadData* td = thread_data.get();
return td->trlist->check(atr);
}

void set_thread_resource(const ResolvedCallReferenceNode* rcr, const QoreValue arg) {
thread_data.get()->trlist->set(rcr, arg);
thread_data.get()->trlist->set(rcr, arg);
}

int remove_thread_resource(const ResolvedCallReferenceNode* rcr, ExceptionSink* xsink) {
return thread_data.get()->trlist->remove(rcr, xsink);
return thread_data.get()->trlist->remove(rcr, xsink);
}

void mark_thread_resources() {
ThreadData* td = thread_data.get();
ThreadResourceList* trl = new ThreadResourceList(td->trlist);
td->trlist = trl;
ThreadData* td = thread_data.get();
ThreadResourceList* trl = new ThreadResourceList(td->trlist);
td->trlist = trl;
}


// returns 0 if the last mark has been cleared, -1 if there are more marks to check
static int purge_thread_resources_to_mark(ThreadData* td, ExceptionSink* xsink) {
td->trlist->purge(xsink);
td->trlist->purge(xsink);

if (td->trlist->prev) {
ThreadResourceList* tr = td->trlist;
td->trlist = tr->prev;
delete tr;
return -1;
}
return 0;
if (td->trlist->prev) {
ThreadResourceList* tr = td->trlist;
td->trlist = tr->prev;
delete tr;
return -1;
}
return 0;
}

// returns 0 if the last mark has been cleared, -1 if there are more marks to check
int purge_thread_resources_to_mark(ExceptionSink* xsink) {
ThreadData* td = thread_data.get();
return purge_thread_resources_to_mark(td, xsink);
ThreadData* td = thread_data.get();
return purge_thread_resources_to_mark(td, xsink);
}

void purge_thread_resources(ExceptionSink* xsink) {
ThreadData* td = thread_data.get();
while (purge_thread_resources_to_mark(td, xsink));
ThreadData* td = thread_data.get();
while (purge_thread_resources_to_mark(td, xsink));
}

void purge_pgm_thread_resources(const QoreProgram* pgm, ExceptionSink* xsink) {
ThreadData* td = thread_data.get();
ThreadData* td = thread_data.get();

ThreadResourceList* tr = td->trlist;
while (tr) {
tr->purge(pgm, xsink);
tr = tr->prev;
}
ThreadResourceList* tr = td->trlist;
while (tr) {
tr->purge(pgm, xsink);
tr = tr->prev;
}
}

void parse_try_module_inc() {
ThreadData* td = thread_data.get();
td->tm.inc();
ThreadData* td = thread_data.get();
td->tm.inc();
}

bool parse_try_module_dec(const QoreProgramLocation* loc) {
ThreadData* td = thread_data.get();
return td->tm.dec(loc);
ThreadData* td = thread_data.get();
return td->tm.dec(loc);
}

unsigned parse_try_module_get() {
return thread_data.get()->tm.count;
return thread_data.get()->tm.count;
}

void parse_try_module_set(unsigned c) {
thread_data.get()->tm.count = c;
thread_data.get()->tm.count = c;
}

void parse_cond_push(bool mark) {
ThreadData* td = thread_data.get();
if (!td->pcs)
td->pcs = new ParseConditionalStack;
td->pcs->push(mark);
ThreadData* td = thread_data.get();
if (!td->pcs)
td->pcs = new ParseConditionalStack;
td->pcs->push(mark);
}

bool parse_cond_else() {
ThreadData* td = thread_data.get();
return td->pcs ? td->pcs->checkElse() : false;
ThreadData* td = thread_data.get();
return td->pcs ? td->pcs->checkElse() : false;
}

bool parse_cond_pop(const QoreProgramLocation* loc) {
ThreadData* td = thread_data.get();
if (!td->pcs) {
parse_error(*loc, "unmatched %%endif");
return false;
}
return td->pcs->pop(loc);
ThreadData* td = thread_data.get();
if (!td->pcs) {
parse_error(*loc, "unmatched %%endif");
return false;
}
return td->pcs->pop(loc);
}

bool parse_cond_test(const QoreProgramLocation* loc) {
ThreadData* td = thread_data.get();
if (!td->pcs) {
parse_error(*loc, "%%else without %%ifdef");
return false;
}
return td->pcs->test(loc);
ThreadData* td = thread_data.get();
if (!td->pcs) {
parse_error(*loc, "%%else without %%ifdef");
return false;
}
return td->pcs->test(loc);
}

void push_parse_options() {
ThreadData* td = thread_data.get();
qore_program_private::get(*td->current_pgm)->pushParseOptions(td->parse_file);
ThreadData* td = thread_data.get();
qore_program_private::get(*td->current_pgm)->pushParseOptions(td->parse_file);
}

// called when a StatementBlock has "on_exit" blocks
void pushBlock(block_list_t::iterator i) {
ThreadData* td = thread_data.get();
td->on_block_exit_list.push_back(i);
ThreadData* td = thread_data.get();
td->on_block_exit_list.push_back(i);
}

// called when a StatementBlock has "on_exit" blocks
block_list_t::iterator popBlock() {
ThreadData* td = thread_data.get();
block_list_t::iterator i = td->on_block_exit_list.back();
td->on_block_exit_list.pop_back();
return i;
ThreadData* td = thread_data.get();
block_list_t::iterator i = td->on_block_exit_list.back();
td->on_block_exit_list.pop_back();
return i;
}

// called by each "on_exit" statement to activate its code for the block exit
void advanceOnBlockExit() {
ThreadData* td = thread_data.get();
--td->on_block_exit_list.back();
ThreadData* td = thread_data.get();
--td->on_block_exit_list.back();
}

// new file name, current parse state
Expand Down
8 changes: 6 additions & 2 deletions qore.spec-fedora
Expand Up @@ -2,7 +2,7 @@
%global user_module_dir %{_datadir}/qore-modules/

Name: qore
Version: 0.9.14
Version: 0.9.15
Release: 1%{?dist}
Summary: Multithreaded Programming Language

Expand Down Expand Up @@ -45,7 +45,7 @@ This package provides the qore library required for all clients using qore
functionality.

%files -n libqore
%{_libdir}/libqore.so.6.3.4
%{_libdir}/libqore.so.6.3.5
%{_libdir}/libqore.so.6
%license COPYING.LGPL COPYING.GPL COPYING.MIT README-LICENSE
%doc README.md README-MODULES RELEASE-NOTES AUTHORS ABOUT
Expand Down Expand Up @@ -174,6 +174,10 @@ make check
%{_mandir}/man1/qore.1.*

%changelog
* Sat May 1 2021 David Nichols <david@qore.org> 0.9.15-1
- updated version to 0.9.15-1
- updated libqore version to 6.3.5

* Tue Apr 6 2021 David Nichols <david@qore.org> 0.9.14-1
- updated version to 0.9.14-1

Expand Down
6 changes: 5 additions & 1 deletion qore.spec-multi
Expand Up @@ -31,7 +31,7 @@

Summary: Multithreaded Programming Language
Name: qore
Version: 0.9.14
Version: 0.9.15
Release: 1%{dist}
%if 0%{?suse_version}
License: LGPL-2.0+ or GPL-2.0+ or MIT
Expand Down Expand Up @@ -277,6 +277,10 @@ rm -rf $RPM_BUILD_ROOT
%endif

%changelog
* Sat May 1 2021 David Nichols <david@qore.org> 0.9.15
- updated version to 0.9.15
- updated libqore version to 6.3.5

* Tue Apr 6 2021 David Nichols <david@qore.org> 0.9.14
- updated version to 0.9.14

Expand Down

0 comments on commit 2b72a2f

Please sign in to comment.