Skip to content

Commit aa625bb

Browse files
authored
Merge pull request #43 from qorelanguage/bugfix/4272_process_fixes_09x
refs qorelanguage/qore#4272 fixed issues related to returning the pro…
2 parents 998a71c + b47ae41 commit aa625bb

File tree

3 files changed

+103
-80
lines changed

3 files changed

+103
-80
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ option(USE_INTERNAL_BOOST "Enforce using internal copy of boost libraries" OFF)
88

99
set (VERSION_MAJOR 1)
1010
set (VERSION_MINOR 0)
11-
set (VERSION_PATCH 0)
11+
set (VERSION_PATCH 1)
1212

1313
# where to look first for cmake modules, before ${CMAKE_ROOT}/Modules/ is checked
1414
set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake )

src/process.qpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ Version 1.0. (See http://www.boost.org/LICENSE_1_0.txt)
5353

5454
@section process_relnotes Process Module Release History
5555

56+
@subsection process_v1_0_1 process v1.0.1
57+
- fixed bugs handling retrieving process status for already-terminated processes; addressed exception handling
58+
issues
59+
(<a href="https://github.com/qorelanguage/qore/issues/4272">issue 4272</a>)
60+
5661
@subsection process_v1_0_0 process v1.0.0
5762
- added:
5863
- @ref Qore::Process::Process::readStdoutBinary() "Process::readStdoutBinary()"

src/processpriv.cpp

Lines changed: 97 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
Qore Programming Language process Module
33
4-
Copyright (C) 2003 - 2020 Qore Technologies, s.r.o.
4+
Copyright (C) 2003 - 2021 Qore Technologies, s.r.o.
55
66
Permission is hereby granted, free of charge, to any person obtaining a
77
copy of this software and associated documentation files (the "Software"),
@@ -46,18 +46,18 @@ DLLLOCAL extern const TypedHashDecl* hashdeclMemorySummaryInfo;
4646
static int page_size = sysconf(_SC_PAGESIZE);
4747

4848
ProcessPriv::ProcessPriv(pid_t pid, ExceptionSink* xsink) :
49-
m_asio_ctx(),
50-
m_in_pipe(m_asio_ctx),
51-
m_out_pipe(m_asio_ctx),
52-
m_err_pipe(m_asio_ctx),
53-
54-
m_in_buf(&bg_xsink),
55-
m_out_buf(&bg_xsink),
56-
m_err_buf(&bg_xsink),
57-
58-
m_in_asiobuf(boost::asio::buffer(m_in_vec)),
59-
m_out_asiobuf(boost::asio::buffer(m_out_vec)),
60-
m_err_asiobuf(boost::asio::buffer(m_err_vec)) {
49+
m_asio_ctx(),
50+
m_in_pipe(m_asio_ctx),
51+
m_out_pipe(m_asio_ctx),
52+
m_err_pipe(m_asio_ctx),
53+
54+
m_in_buf(&bg_xsink),
55+
m_out_buf(&bg_xsink),
56+
m_err_buf(&bg_xsink),
57+
58+
m_in_asiobuf(boost::asio::buffer(m_in_vec)),
59+
m_out_asiobuf(boost::asio::buffer(m_out_vec)),
60+
m_err_asiobuf(boost::asio::buffer(m_err_vec)) {
6161
try {
6262
int i = boost::numeric_cast<int>(pid);
6363
m_process = new bp::child(i);
@@ -70,21 +70,21 @@ ProcessPriv::ProcessPriv(pid_t pid, ExceptionSink* xsink) :
7070
static constexpr unsigned process_buf_size = 4096;
7171

7272
ProcessPriv::ProcessPriv(const char* command, const QoreListNode* arguments, const QoreHashNode *opts, ExceptionSink* xsink) :
73-
m_asio_ctx(),
74-
m_in_pipe(m_asio_ctx),
75-
m_out_pipe(m_asio_ctx),
76-
m_err_pipe(m_asio_ctx),
73+
m_asio_ctx(),
74+
m_in_pipe(m_asio_ctx),
75+
m_out_pipe(m_asio_ctx),
76+
m_err_pipe(m_asio_ctx),
7777

78-
m_in_buf(&bg_xsink),
79-
m_out_buf(&bg_xsink),
80-
m_err_buf(&bg_xsink),
78+
m_in_buf(&bg_xsink),
79+
m_out_buf(&bg_xsink),
80+
m_err_buf(&bg_xsink),
8181

82-
m_out_vec(process_buf_size),
83-
m_err_vec(process_buf_size),
82+
m_out_vec(process_buf_size),
83+
m_err_vec(process_buf_size),
8484

85-
m_in_asiobuf(boost::asio::buffer(m_in_vec)),
86-
m_out_asiobuf(boost::asio::buffer(m_out_vec)),
87-
m_err_asiobuf(boost::asio::buffer(m_err_vec)) {
85+
m_in_asiobuf(boost::asio::buffer(m_in_vec)),
86+
m_out_asiobuf(boost::asio::buffer(m_out_vec)),
87+
m_err_asiobuf(boost::asio::buffer(m_err_vec)) {
8888
// get handler pointers
8989
ResolvedCallReferenceNode* on_success = optsExecutor("on_success", opts, xsink);
9090
ResolvedCallReferenceNode* on_setup = optsExecutor("on_setup", opts, xsink);
@@ -389,7 +389,7 @@ boost::filesystem::path ProcessPriv::optsPath(const char* command, const QoreHas
389389
}
390390
} catch (std::runtime_error& ex) {
391391
xsink->raiseException("PROCESS-SEARCH-PATH-ERROR", ex.what());
392-
return ret;
392+
return ret;
393393
}
394394

395395
if (ret.empty()) {
@@ -594,7 +594,11 @@ void ProcessPriv::launchChild(boost::filesystem::path p,
594594
m_out_buf.reassignThread();
595595
m_err_buf.reassignThread();
596596

597-
m_asio_ctx.run();
597+
try {
598+
m_asio_ctx.run();
599+
} catch (const std::exception& ex) {
600+
printd(0, "exception in m_asio_ctx.run() in m_asio_ctx_run_future: %s", ex.what());
601+
}
598602

599603
m_out_buf.unassignThread();
600604
m_err_buf.unassignThread();
@@ -604,15 +608,17 @@ void ProcessPriv::launchChild(boost::filesystem::path p,
604608
}
605609

606610
int ProcessPriv::exitCode(ExceptionSink* xsink) {
607-
if (!processCheck(xsink))
611+
if (!processCheck(xsink)) {
608612
return -1;
613+
}
609614

610615
return exit_code;
611616
}
612617

613618
int ProcessPriv::id(ExceptionSink* xsink) {
614-
if (!processCheck(xsink))
619+
if (!processCheck(xsink)) {
615620
return -1;
621+
}
616622

617623
try {
618624
return m_process->id();
@@ -624,8 +630,9 @@ int ProcessPriv::id(ExceptionSink* xsink) {
624630
}
625631

626632
bool ProcessPriv::valid(ExceptionSink* xsink) {
627-
if (!processCheck(xsink))
633+
if (!processCheck(xsink)) {
628634
return false;
635+
}
629636

630637
try {
631638
return m_process->valid();
@@ -637,23 +644,27 @@ bool ProcessPriv::valid(ExceptionSink* xsink) {
637644
}
638645

639646
bool ProcessPriv::running(ExceptionSink* xsink) {
640-
if (!processCheck(xsink))
647+
if (!processCheck(xsink)) {
641648
return false;
642-
643-
try {
644-
return m_process->running();
645-
} catch (const std::exception& ex) {
646-
xsink->raiseException("PROCESS-RUNNING-ERROR", ex.what());
647649
}
648650

649-
return false;
651+
std::error_code ec;
652+
bool rc = m_process->running(ec);
653+
if (ec) {
654+
xsink->raiseException("PROCESS-RUNNING-ERROR", "Process::running() failed: %s", ec.message().c_str());
655+
}
656+
return rc;
650657
}
651658

652659
void ProcessPriv::finalizeStreams(ExceptionSink* xsink) {
653660
// the asio context is stopped in the process handler unless the proces has been detached
654661
if (detached) {
655662
m_asio_ctx.stop();
656-
m_asio_ctx.run();
663+
try {
664+
m_asio_ctx.run();
665+
} catch (const std::exception& ex) {
666+
printd(0, "exception in m_asio_ctx.run() in ProcessPriv::finalizeStreams(): %s", ex.what());
667+
}
657668
}
658669

659670
// wait for future
@@ -718,12 +729,23 @@ void ProcessPriv::getExitCode(ExceptionSink* xsink) {
718729
}
719730

720731
bool ProcessPriv::wait(ExceptionSink* xsink) {
721-
if (!processCheck(xsink))
732+
if (!processCheck(xsink)) {
722733
return false;
734+
}
735+
736+
// return immediately if we already have an exit code
737+
if (exit_code != -1) {
738+
return true;
739+
}
723740

724741
try {
725742
if (m_process->valid()) {
726-
m_process->wait();
743+
std::error_code ec;
744+
m_process->wait(ec);
745+
if (ec) {
746+
xsink->raiseException("PROCESS-WAIT-ERROR", "cannot wait on process: %s", ec.message().c_str());
747+
return false;
748+
}
727749

728750
// get exit code if possible
729751
getExitCode(xsink);
@@ -733,30 +755,31 @@ bool ProcessPriv::wait(ExceptionSink* xsink) {
733755
}
734756
return true;
735757
} catch (const std::exception& ex) {
736-
// ignore errors if the process has already terminated
737758
const char* err = ex.what();
738-
if (!strcmp("wait error: No child processes", err)) {
739-
// get exit code if possible
740-
getExitCode(xsink);
741-
742-
// rethrows any background exceptions
743-
finalizeStreams(xsink);
744-
return true;
745-
} else {
746-
xsink->raiseException("PROCESS-WAIT-ERROR", err);
747-
}
759+
xsink->raiseException("PROCESS-WAIT-ERROR", err);
748760
}
749761

750762
return false;
751763
}
752764

753765
bool ProcessPriv::wait(int64 t, ExceptionSink* xsink) {
754-
if (!processCheck(xsink))
766+
if (!processCheck(xsink)) {
755767
return false;
768+
}
769+
770+
// return immediately if we already have an exit code
771+
if (exit_code != -1) {
772+
return true;
773+
}
756774

757775
try {
758-
if (m_process->valid() && m_process->running()) {
759-
bool rv = m_process->wait_for(std::chrono::milliseconds(t));
776+
if (m_process->valid()) {
777+
std::error_code ec;
778+
bool rv = m_process->wait_for(std::chrono::milliseconds(t), ec);
779+
if (ec) {
780+
xsink->raiseException("PROCESS-WAIT-ERROR", "cannot wait on process: %s", ec.message().c_str());
781+
return false;
782+
}
760783
if (rv) {
761784
// get exit code if possible
762785
getExitCode(xsink);
@@ -769,47 +792,41 @@ bool ProcessPriv::wait(int64 t, ExceptionSink* xsink) {
769792
}
770793
return false;
771794
} catch (const std::exception& ex) {
772-
// ignore errors if the process has already terminated
773795
const char* err = ex.what();
774-
if (!strcmp("wait error: No child processes", err)) {
775-
// get exit code if possible
776-
try {
777-
exit_code = m_process->exit_code();
778-
} catch (const std::exception& ex) {
779-
xsink->raiseException("PROCESS-EXITCODE-ERROR", ex.what());
780-
}
781-
// rethrows any background exceptions
782-
finalizeStreams(xsink);
783-
return true;
784-
} else {
785-
xsink->raiseException("PROCESS-WAIT-ERROR", err);
786-
}
796+
xsink->raiseException("PROCESS-WAIT-ERROR", err);
787797
}
788798

789799
return false;
790800
}
791801

792802
bool ProcessPriv::detach(ExceptionSink* xsink) {
793-
if (!processCheck(xsink))
803+
if (!processCheck(xsink)) {
794804
return false;
805+
}
795806

796-
m_process->detach();
807+
try {
808+
m_process->detach();
809+
} catch (const std::exception& ex) {
810+
const char* err = ex.what();
811+
xsink->raiseException("PROCESS-WAIT-ERROR", err);
812+
return false;
813+
}
797814
detached = true;
798815
return true;
799816
}
800817

801818
bool ProcessPriv::terminate(ExceptionSink* xsink) {
802-
if (!processCheck(xsink))
819+
if (!processCheck(xsink)) {
803820
return false;
804-
805-
try {
806-
m_process->terminate();
807-
return true;
808-
} catch (const std::exception& ex) {
809-
xsink->raiseException("PROCESS-TERMINATE-ERROR", ex.what());
810821
}
811822

812-
return false;
823+
std::error_code ec;
824+
m_process->terminate(ec);
825+
if (ec) {
826+
xsink->raiseException("PROCESS-TERMINATE-ERROR", "cannot terminate process: %s", ec.message().c_str());
827+
return false;
828+
}
829+
return true;
813830
}
814831

815832
QoreStringNode* ProcessPriv::readStderr(size_t n, ExceptionSink* xsink) {
@@ -981,8 +998,9 @@ BinaryNode* ProcessPriv::readStdoutBinaryTimeout(size_t n, int64 millis, Excepti
981998
}
982999

9831000
void ProcessPriv::write(const char* val, size_t n, ExceptionSink* xsink) {
984-
if (!processCheck(xsink))
1001+
if (!processCheck(xsink)) {
9851002
return;
1003+
}
9861004

9871005
if (!val || !n)
9881006
return;

0 commit comments

Comments
 (0)