• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

antonvw / wex / 19969138048

05 Dec 2025 04:23PM UTC coverage: 64.381% (+0.008%) from 64.373%
19969138048

push

github

antonvw
git grep improve

18567 of 31609 branches covered (58.74%)

Branch coverage included in aggregate %.

14733 of 20114 relevant lines covered (73.25%)

1521.34 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

66.22
/src/factory/process-imp.cpp
1
////////////////////////////////////////////////////////////////////////////////
2
// Name:      process-imp.cpp
3
// Purpose:   Implementation of class wex::factory::process_imp
4
// Author:    Anton van Wezenbeek
5
// Copyright: (c) 2021-2025 Anton van Wezenbeek
6
////////////////////////////////////////////////////////////////////////////////
7

8
#include <thread>
9

10
#include <wex/core/log.h>
11
#include <wex/factory/defs.h>
12
#include <wex/factory/process.h>
13
#include <wx/event.h>
14

15
#include <boost/process/v1/async_system.hpp>
16

17
#include "process-imp.h"
18

19
#define WEX_POST(ID, TEXT, DEST)                                               \
20
  if (DEST != nullptr)                                                         \
21
  {                                                                            \
22
    wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED, ID);                     \
23
    event.SetString(TEXT);                                                     \
24
    wxPostEvent(DEST, event);                                                  \
25
  }
26

27
wex::factory::process_imp::process_imp()
9✔
28
  : m_io(std::make_shared<boost::asio::io_context>())
9✔
29
  , m_queue(std::make_shared<std::queue<std::string>>())
9✔
30
{
31
}
9✔
32

33
void wex::factory::process_imp::async_sleep_for(
2✔
34
  const std::chrono::milliseconds& ms)
35
{
36
  std::this_thread::sleep_for(ms);
2✔
37
}
2✔
38

39
void wex::factory::process_imp::async_system(process* p)
9✔
40
{
41
  m_debug.store(p->m_eh_debug != nullptr);
9✔
42

43
  try
44
  {
45
    boost_async_system(p);
9✔
46

47
    m_is_running.store(true);
8✔
48

49
    thread_input(p);
8✔
50
    thread_output(p);
8✔
51
    thread_error(p);
8✔
52
  }
53
  catch (std::exception& e)
1!
54
  {
55
    log("async_system") << e.what();
1✔
56
  }
1✔
57
}
9✔
58

59
void wex::factory::process_imp::boost_async_system(process* p)
9✔
60
{
61
  bp1::async_system(
8✔
62
    *m_io.get(),
8✔
63
    [this, p](boost::system::error_code error, int i)
8✔
64
    {
65
      m_is_running.store(false);
4✔
66

67
      if (error.value() != 0 && p->m_eh_out != nullptr)
4!
68
      {
69
        WEX_POST(ID_SHELL_APPEND_ERROR, error.message(), p->m_eh_out)
×
70
      }
71

72
      log::debug("async_system") << "exit" << p->data().exe();
4✔
73

74
      if (m_debug.load())
4!
75
      {
76
        WEX_POST(ID_DEBUG_EXIT, "", p->m_eh_debug)
×
77
      }
78
    },
4✔
79

80
    // clang-format off
81
    p->data().exe_path(),
17✔
82
    bp1::args = p->data().args(),
20✔
83
    bp1::start_dir = p->data().start_dir(),
19✔
84
    bp1::std_err > m_es,
10✔
85
    bp1::std_in < m_os,
10✔
86
    bp1::std_out > m_is,
9✔
87
    m_group);
9✔
88
  // clang-format on
89

90
  log::debug("async_system")
16✔
91
    << p->data().exe() << "wd:" << p->data().start_dir();
8✔
92

93
  WEX_POST(ID_SHELL_APPEND, p->data().exe() + "\n", p->m_eh_out)
8!
94
}
8✔
95

96
bool wex::factory::process_imp::stop(wxEvtHandler* e)
12✔
97
{
98
  if (m_is_running.load())
12✔
99
  {
100
    if (m_group.valid())
4!
101
    {
102
      m_group.terminate();
4✔
103
    }
104

105
    m_io->stop();
4✔
106
    m_is_running.store(false);
4✔
107

108
    if (m_debug.load() && e != nullptr)
4!
109
    {
110
      WEX_POST(ID_DEBUG_EXIT, "", e)
×
111
    }
112

113
    return true;
4✔
114
  }
115

116
  return false;
8✔
117
}
118

119
void wex::factory::process_imp::thread_error(const process* p)
8✔
120
{
121
  std::thread v(
122
    [debug = m_debug.load(),
8✔
123
     &dbg  = p->m_eh_debug,
8✔
124
     out   = p->m_eh_out,
8✔
125
     &es   = m_es]
8✔
126
    {
127
      std::string text;
8✔
128

129
      while (es.good())
24✔
130
      {
131
        text.push_back(es.get());
8✔
132

133
        if (text.back() == '\n')
8!
134
        {
135
          WEX_POST(ID_SHELL_APPEND_ERROR, text, out)
×
136

137
          if (debug)
×
138
          {
139
            WEX_POST(ID_DEBUG_STDOUT, text, dbg)
×
140
          }
141

142
          text.clear();
×
143
        }
144
      }
145
    });
16✔
146

147
  v.detach();
8✔
148
}
8✔
149

150
void wex::factory::process_imp::thread_input(const process* p)
8✔
151
{
152
  std::thread t(
153
    [debug = m_debug.load(),
8✔
154
     &dbg  = p->m_eh_debug,
8✔
155
     &out  = p->m_eh_out,
8✔
156
     &is   = m_is]
8✔
157
    {
158
      std::string text, line;
8✔
159
      line.reserve(1000000);
8✔
160
      text.reserve(1000000);
8✔
161
      int  linesize = 0;
8✔
162
      bool error    = false;
8✔
163

164
      while (is.good() && !error)
449!
165
      {
166
        text.push_back(is.get());
441✔
167
        linesize++;
441✔
168

169
        if (linesize > 20000)
441!
170
        {
171
          error = true;
×
172
          WEX_POST(ID_SHELL_APPEND, "\n*** LINE LIMIT ***\n", out)
×
173
        }
174
        else if (isspace(text.back()))
441✔
175
        {
176
          WEX_POST(ID_SHELL_APPEND, text, out)
29!
177

178
          if (text.back() == '\n')
29✔
179
          {
180
            linesize = 0;
28✔
181
          }
182

183
          if (debug)
29!
184
          {
185
            line.append(text);
×
186

187
            if (line.back() == '\n')
×
188
            {
189
              WEX_POST(ID_DEBUG_STDOUT, line, dbg)
×
190
              line.clear();
×
191
            }
192
          }
193

194
          text.clear();
29✔
195
        }
196
      }
197
    });
16✔
198

199
  t.detach();
8✔
200
}
8✔
201

202
void wex::factory::process_imp::thread_output(const process* p)
8✔
203
{
204
  std::thread u(
205
    [debug = m_debug.load(),
16!
206
     io    = m_io,
8✔
207
     &os   = m_os,
8✔
208
     dbg   = p->m_eh_debug,
8✔
209
     queue = m_queue]
8✔
210
    {
211
      while (os.good() && !io->stopped())
28!
212
      {
213
        io->run_one_for(std::chrono::milliseconds(10));
12✔
214

215
        if (!queue->empty())
12✔
216
        {
217
          if (const auto& text(queue->front()); os.good() && !io->stopped())
2!
218
          {
219
            log::debug("async_system") << "write:" << text;
×
220

221
            os << text << "\n";
×
222

223
            if (debug)
×
224
            {
225
              WEX_POST(ID_DEBUG_STDIN, text, dbg)
×
226
            }
227
          }
228
          else
229
          {
230
            log::debug("async_system") << "skip:" << text;
4✔
231
          }
232

233
          queue->pop();
2✔
234
        }
235
      }
236
    });
16✔
237

238
  u.detach();
8✔
239
}
8✔
240

241
bool wex::factory::process_imp::write(const std::string& text)
5✔
242
{
243
  if (text.empty() || !m_is_running.load())
5!
244
  {
245
    return false;
1✔
246
  }
247

248
  m_queue->push(text);
4✔
249

250
  return true;
4✔
251
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc