Skip to content

Commit ed2608b

Browse files
committed
workshop: implement TERMINATE_CHILDREN for "translate" and "spawn"
1 parent 7d6a968 commit ed2608b

File tree

7 files changed

+74
-1
lines changed

7 files changed

+74
-1
lines changed

debian/changelog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
cm4all-workshop (7.2) unstable; urgency=low
22

33
* workshop: disable plan UID check for "translate" plans
4+
* workshop: implement TERMINATE_CHILDREN for "translate" and "spawn"
45
* cron: support multiple CHILD_TAGs for TERMINATE_CHILDREN
56

67
--

src/Instance.cxx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,9 +216,13 @@ Instance::OnControlPacket(BengControl::Command command,
216216
break;
217217

218218
case Command::TERMINATE_CHILDREN:
219-
if (const auto tag = ToStringView(payload); !tag.empty())
219+
if (const auto tag = ToStringView(payload); !tag.empty()) {
220+
for (auto &i : partitions)
221+
i.TerminateChildren(tag);
220222
for (auto &i : cron_partitions)
221223
i.TerminateChildren(tag);
224+
}
225+
222226
break;
223227

224228
case Command::DISABLE_QUEUE:

src/workshop/Operator.cxx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
#include "co/Task.hxx"
3434
#include "util/DeleteDisposer.hxx"
3535
#include "util/StringCompare.hxx"
36+
#include "util/StringList.hxx"
3637
#include "util/UTF8.hxx"
3738
#include "AllocatorPtr.hxx"
3839
#include "CgroupAccounting.hxx"
@@ -87,6 +88,12 @@ WorkshopOperator::~WorkshopOperator() noexcept
8788
children.clear_and_dispose(DeleteDisposer{});
8889
}
8990

91+
bool
92+
WorkshopOperator::IsChildTag(std::string_view value) const noexcept
93+
{
94+
return StringListContains(child_tag, '\0', value);
95+
}
96+
9097
inline UniqueFileDescriptor
9198
WorkshopOperator::InitLog(std::size_t max_log_buffer,
9299
bool enable_journal)
@@ -240,6 +247,11 @@ WorkshopOperator::Start2(std::size_t max_log_buffer,
240247
job.plan_name.c_str(),
241248
"", nullptr,
242249
job.args);
250+
251+
if (translation.execute_options != nullptr &&
252+
!translation.execute_options->child_options.tag.empty() &&
253+
child_tag.empty())
254+
child_tag = translation.execute_options->child_options.tag;
243255
}
244256

245257
auto &spawn_service = workplace.GetSpawnService();
@@ -349,6 +361,17 @@ WorkshopOperator::Start2(std::size_t max_log_buffer,
349361
}
350362
}
351363

364+
void
365+
WorkshopOperator::Cancel() noexcept
366+
{
367+
logger(2, "cancel");
368+
369+
job.SetDone(-1, "Canceled");
370+
371+
/* we do not kill the process because this will be done
372+
implicitly by our destructor */
373+
}
374+
352375
inline void
353376
WorkshopOperator::OnTaskCompletion(std::exception_ptr &&error) noexcept
354377
{
@@ -594,6 +617,11 @@ WorkshopOperator::OnControlSpawn(const char *token, const char *param)
594617
token, param,
595618
{});
596619

620+
if (response.execute_options != nullptr &&
621+
!response.execute_options->child_options.tag.empty() &&
622+
child_tag.empty())
623+
child_tag = response.execute_options->child_options.tag;
624+
597625
auto &spawn_service = workplace.GetSpawnService();
598626

599627
co_await CoEnqueueSpawner{spawn_service};

src/workshop/Operator.hxx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ class WorkshopOperator final
5858

5959
const LazyDomainLogger logger;
6060

61+
/**
62+
* The CHILD_TAG value from the translation response. Used to
63+
* implement the control command TERMINATE_CHILDREN.
64+
*/
65+
std::string child_tag;
66+
6167
FarTimerEvent timeout_event;
6268

6369
std::unique_ptr<ProgressReader> progress_reader;
@@ -107,9 +113,23 @@ public:
107113
return job.plan_name;
108114
}
109115

116+
[[gnu::pure]]
117+
bool IsChildTag(std::string_view value) const noexcept;
118+
110119
void Start(std::size_t max_log_buffer,
111120
bool enable_journal) noexcept;
112121

122+
/**
123+
* Kill the process and put the database record in a complete
124+
* and failed state, but do not invoke the #WorkshopWorkplace
125+
* (because that is supposed to be the caller who already
126+
* knows the job completes).
127+
*
128+
* After this method returns, the caller is supposed to delete
129+
* this object.
130+
*/
131+
void Cancel() noexcept;
132+
113133
private:
114134
[[nodiscard]]
115135
Co::InvokeTask Start2(std::size_t max_log_buffer,

src/workshop/Partition.hxx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,10 @@ public:
9191
queue.EnableAdmin();
9292
}
9393

94+
void TerminateChildren(std::string_view child_tag) noexcept {
95+
workplace.CancelTag(child_tag);
96+
}
97+
9498
void UpdateFilter(bool library_modified=false) noexcept;
9599
void UpdateLibraryAndFilter(bool force) noexcept;
96100

src/workshop/Workplace.cxx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,3 +112,17 @@ WorkshopWorkplace::OnTimeout(WorkshopOperator *o) noexcept
112112
{
113113
OnExit(o);
114114
}
115+
116+
void
117+
WorkshopWorkplace::CancelTag(std::string_view tag) noexcept
118+
{
119+
const auto n = operators.remove_and_dispose_if([tag](const auto &o){
120+
return o.IsChildTag(tag);
121+
}, [](auto *o) {
122+
o->Cancel();
123+
delete o;
124+
});
125+
126+
if (n > 0)
127+
exit_listener.OnChildProcessExit(-1);
128+
}

src/workshop/Workplace.hxx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,6 @@ public:
9898

9999
void OnExit(WorkshopOperator *o) noexcept;
100100
void OnTimeout(WorkshopOperator *o) noexcept;
101+
102+
void CancelTag(std::string_view tag) noexcept;
101103
};

0 commit comments

Comments
 (0)