1
1
/*
2
2
Qore Programming Language process Module
3
3
4
- Copyright (C) 2003 - 2020 Qore Technologies, s.r.o.
4
+ Copyright (C) 2003 - 2021 Qore Technologies, s.r.o.
5
5
6
6
Permission is hereby granted, free of charge, to any person obtaining a
7
7
copy of this software and associated documentation files (the "Software"),
@@ -46,18 +46,18 @@ DLLLOCAL extern const TypedHashDecl* hashdeclMemorySummaryInfo;
46
46
static int page_size = sysconf(_SC_PAGESIZE);
47
47
48
48
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)) {
61
61
try {
62
62
int i = boost::numeric_cast<int >(pid);
63
63
m_process = new bp::child (i);
@@ -70,21 +70,21 @@ ProcessPriv::ProcessPriv(pid_t pid, ExceptionSink* xsink) :
70
70
static constexpr unsigned process_buf_size = 4096 ;
71
71
72
72
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),
77
77
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),
81
81
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),
84
84
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)) {
88
88
// get handler pointers
89
89
ResolvedCallReferenceNode* on_success = optsExecutor (" on_success" , opts, xsink);
90
90
ResolvedCallReferenceNode* on_setup = optsExecutor (" on_setup" , opts, xsink);
@@ -389,7 +389,7 @@ boost::filesystem::path ProcessPriv::optsPath(const char* command, const QoreHas
389
389
}
390
390
} catch (std::runtime_error& ex) {
391
391
xsink->raiseException (" PROCESS-SEARCH-PATH-ERROR" , ex.what ());
392
- return ret;
392
+ return ret;
393
393
}
394
394
395
395
if (ret.empty ()) {
@@ -594,7 +594,11 @@ void ProcessPriv::launchChild(boost::filesystem::path p,
594
594
m_out_buf.reassignThread ();
595
595
m_err_buf.reassignThread ();
596
596
597
- m_asio_ctx.run ();
597
+ try {
598
+ m_asio_ctx.run ();
599
+ } catch (const std::exception& e) {
600
+ printd (0 , " exception in m_asio_ctx.run() in m_asio_ctx_run_future: %s" , ex.what ());
601
+ }
598
602
599
603
m_out_buf.unassignThread ();
600
604
m_err_buf.unassignThread ();
@@ -604,15 +608,17 @@ void ProcessPriv::launchChild(boost::filesystem::path p,
604
608
}
605
609
606
610
int ProcessPriv::exitCode (ExceptionSink* xsink) {
607
- if (!processCheck (xsink))
611
+ if (!processCheck (xsink)) {
608
612
return -1 ;
613
+ }
609
614
610
615
return exit_code;
611
616
}
612
617
613
618
int ProcessPriv::id (ExceptionSink* xsink) {
614
- if (!processCheck (xsink))
619
+ if (!processCheck (xsink)) {
615
620
return -1 ;
621
+ }
616
622
617
623
try {
618
624
return m_process->id ();
@@ -624,8 +630,9 @@ int ProcessPriv::id(ExceptionSink* xsink) {
624
630
}
625
631
626
632
bool ProcessPriv::valid (ExceptionSink* xsink) {
627
- if (!processCheck (xsink))
633
+ if (!processCheck (xsink)) {
628
634
return false ;
635
+ }
629
636
630
637
try {
631
638
return m_process->valid ();
@@ -637,23 +644,27 @@ bool ProcessPriv::valid(ExceptionSink* xsink) {
637
644
}
638
645
639
646
bool ProcessPriv::running (ExceptionSink* xsink) {
640
- if (!processCheck (xsink))
647
+ if (!processCheck (xsink)) {
641
648
return false ;
642
-
643
- try {
644
- return m_process->running ();
645
- } catch (const std::exception& ex) {
646
- xsink->raiseException (" PROCESS-RUNNING-ERROR" , ex.what ());
647
649
}
648
650
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;
650
657
}
651
658
652
659
void ProcessPriv::finalizeStreams (ExceptionSink* xsink) {
653
660
// the asio context is stopped in the process handler unless the proces has been detached
654
661
if (detached) {
655
662
m_asio_ctx.stop ();
656
- m_asio_ctx.run ();
663
+ try {
664
+ m_asio_ctx.run ();
665
+ } catch (const std::exception& e) {
666
+ printd (0 , " exception in m_asio_ctx.run() in ProcessPriv::finalizeStreams(): %s" , ex.what ());
667
+ }
657
668
}
658
669
659
670
// wait for future
@@ -718,12 +729,18 @@ void ProcessPriv::getExitCode(ExceptionSink* xsink) {
718
729
}
719
730
720
731
bool ProcessPriv::wait (ExceptionSink* xsink) {
721
- if (!processCheck (xsink))
732
+ if (!processCheck (xsink)) {
722
733
return false ;
734
+ }
723
735
724
736
try {
725
- if (m_process->valid () && m_process->running ()) {
726
- m_process->wait ();
737
+ if (m_process->valid ()) {
738
+ std::error_code ec;
739
+ m_process->wait (ec);
740
+ if (ec) {
741
+ xsink->raiseException (" PROCESS-WAIT-ERROR" , " cannot wait on process: %s" , ec.message ().c_str ());
742
+ return false ;
743
+ }
727
744
728
745
// get exit code if possible
729
746
getExitCode (xsink);
@@ -736,30 +753,26 @@ bool ProcessPriv::wait(ExceptionSink* xsink) {
736
753
}
737
754
return true ;
738
755
} catch (const std::exception& ex) {
739
- // ignore errors if the process has already terminated
740
756
const char * err = ex.what ();
741
- if (!strcmp (" wait error: No child processes" , err)) {
742
- // get exit code if possible
743
- getExitCode (xsink);
744
-
745
- // rethrows any background exceptions
746
- finalizeStreams (xsink);
747
- return true ;
748
- } else {
749
- xsink->raiseException (" PROCESS-WAIT-ERROR" , err);
750
- }
757
+ xsink->raiseException (" PROCESS-WAIT-ERROR" , err);
751
758
}
752
759
753
760
return false ;
754
761
}
755
762
756
763
bool ProcessPriv::wait (int64 t, ExceptionSink* xsink) {
757
- if (!processCheck (xsink))
764
+ if (!processCheck (xsink)) {
758
765
return false ;
766
+ }
759
767
760
768
try {
761
- if (m_process->valid () && m_process->running ()) {
762
- bool rv = m_process->wait_for (std::chrono::milliseconds (t));
769
+ if (m_process->valid ()) {
770
+ std::error_code ec;
771
+ bool rv = m_process->wait_for (std::chrono::milliseconds (t), ec);
772
+ if (ec) {
773
+ xsink->raiseException (" PROCESS-WAIT-ERROR" , " cannot wait on process: %s" , ec.message ().c_str ());
774
+ return false ;
775
+ }
763
776
if (rv) {
764
777
// get exit code if possible
765
778
getExitCode (xsink);
@@ -775,45 +788,41 @@ bool ProcessPriv::wait(int64 t, ExceptionSink* xsink) {
775
788
}
776
789
return false ;
777
790
} catch (const std::exception& ex) {
778
- // ignore errors if the process has already terminated
779
791
const char * err = ex.what ();
780
- if (!strcmp (" wait error: No child processes" , err)) {
781
- // get exit code if possible
782
- getExitCode (xsink);
783
-
784
- // rethrows any background exceptions
785
- finalizeStreams (xsink);
786
-
787
- return true ;
788
- } else {
789
- xsink->raiseException (" PROCESS-WAIT-ERROR" , err);
790
- }
792
+ xsink->raiseException (" PROCESS-WAIT-ERROR" , err);
791
793
}
792
794
793
795
return false ;
794
796
}
795
797
796
798
bool ProcessPriv::detach (ExceptionSink* xsink) {
797
- if (!processCheck (xsink))
799
+ if (!processCheck (xsink)) {
798
800
return false ;
801
+ }
799
802
800
- m_process->detach ();
803
+ try {
804
+ m_process->detach ();
805
+ } catch (const std::exception& ex) {
806
+ const char * err = ex.what ();
807
+ xsink->raiseException (" PROCESS-WAIT-ERROR" , err);
808
+ return false ;
809
+ }
801
810
detached = true ;
802
811
return true ;
803
812
}
804
813
805
814
bool ProcessPriv::terminate (ExceptionSink* xsink) {
806
- if (!processCheck (xsink))
815
+ if (!processCheck (xsink)) {
807
816
return false ;
808
-
809
- try {
810
- m_process->terminate ();
811
- return true ;
812
- } catch (const std::exception& ex) {
813
- xsink->raiseException (" PROCESS-TERMINATE-ERROR" , ex.what ());
814
817
}
815
818
816
- return false ;
819
+ std::error_code ec;
820
+ m_process->terminate (ec);
821
+ if (ec) {
822
+ xsink->raiseException (" PROCESS-TERMINATE-ERROR" , " cannot terminate process: %s" , ec.message ().c_str ());
823
+ return false ;
824
+ }
825
+ return true ;
817
826
}
818
827
819
828
QoreStringNode* ProcessPriv::readStderr (size_t n, ExceptionSink* xsink) {
@@ -985,8 +994,9 @@ BinaryNode* ProcessPriv::readStdoutBinaryTimeout(size_t n, int64 millis, Excepti
985
994
}
986
995
987
996
void ProcessPriv::write (const char * val, size_t n, ExceptionSink* xsink) {
988
- if (!processCheck (xsink))
997
+ if (!processCheck (xsink)) {
989
998
return ;
999
+ }
990
1000
991
1001
if (!val || !n)
992
1002
return ;
0 commit comments