Skip to content

Commit 0d15d7b

Browse files
committed
New static signal handler using
1 parent b40ed81 commit 0d15d7b

8 files changed

Lines changed: 175 additions & 173 deletions

dlib/misc_api/misc_api_kernel_1.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,23 @@ namespace dlib
139139
}
140140
}
141141

142+
// ----------------------------------------------------------------------------------------
143+
144+
BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
145+
{
146+
if (ctrl_type == CTRL_C_EVENT)
147+
{
148+
signal_handler::trigger_interrupt();
149+
return TRUE;
150+
}
151+
return FALSE;
152+
}
153+
154+
void signal_handler::setup()
155+
{
156+
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
157+
}
158+
142159
// ----------------------------------------------------------------------------------------
143160

144161
}

dlib/misc_api/misc_api_kernel_1.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,55 @@ namespace dlib
9898
const std::string& dir
9999
);
100100

101+
// ----------------------------------------------------------------------------------------
102+
103+
struct signal_handler
104+
{
105+
/*!
106+
ensures
107+
- registers a signal handler for SIGINT (Linux/macOS) or CTRL_C_EVENT (Windows)
108+
- when triggered, #is_triggered() will return true
109+
!*/
110+
static void setup();
111+
112+
/*!
113+
ensures
114+
- returns true if the user has pressed Ctrl+C since setup() was called or since
115+
the last reset()
116+
!*/
117+
static bool is_triggered()
118+
{
119+
return get_flag().load();
120+
}
121+
122+
/*!
123+
ensures
124+
- resets the internal triggered flag to false
125+
!*/
126+
static void reset()
127+
{
128+
get_flag().store(false);
129+
}
130+
131+
/*!
132+
ensures
133+
- sets the internal triggered flag to true.
134+
- this function is typically called by the underlying OS-specific signal handler
135+
!*/
136+
static void trigger_interrupt()
137+
{
138+
get_flag().store(true);
139+
}
140+
141+
private:
142+
// Helper to access the singleton atomic flag safely
143+
static std::atomic<bool>& get_flag()
144+
{
145+
static std::atomic<bool> flag(false);
146+
return flag;
147+
}
148+
};
149+
101150
// ----------------------------------------------------------------------------------------
102151

103152
}

dlib/misc_api/misc_api_kernel_2.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <sys/time.h>
1212
#include <sys/stat.h>
1313
#include <sys/types.h>
14+
#include <csignal>
1415
#include <errno.h>
1516

1617
namespace dlib
@@ -115,6 +116,22 @@ namespace dlib
115116
}
116117

117118
// ----------------------------------------------------------------------------------------
119+
120+
void posix_signal_handler(int signal)
121+
{
122+
if (signal == SIGINT)
123+
{
124+
signal_handler::trigger_interrupt();
125+
}
126+
}
127+
128+
void signal_handler::setup()
129+
{
130+
std::signal(SIGINT, posix_signal_handler);
131+
}
132+
133+
// ----------------------------------------------------------------------------------------
134+
118135
}
119136

120137
#endif // DLIB_POSIX

dlib/misc_api/misc_api_kernel_2.h

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,55 @@ namespace dlib
6969
const std::string& dir
7070
);
7171

72+
// ----------------------------------------------------------------------------------------
73+
74+
struct signal_handler
75+
{
76+
/*!
77+
ensures
78+
- registers a signal handler for SIGINT (Linux/macOS) or CTRL_C_EVENT (Windows)
79+
- when triggered, #is_triggered() will return true
80+
!*/
81+
static void setup();
82+
83+
/*!
84+
ensures
85+
- returns true if the user has pressed Ctrl+C since setup() was called or since
86+
the last reset()
87+
!*/
88+
static bool is_triggered()
89+
{
90+
return get_flag().load();
91+
}
92+
93+
/*!
94+
ensures
95+
- resets the internal triggered flag to false
96+
!*/
97+
static void reset()
98+
{
99+
get_flag().store(false);
100+
}
101+
102+
/*!
103+
ensures
104+
- sets the internal triggered flag to true
105+
- this function is typically called by the underlying OS-specific signal handler
106+
!*/
107+
static void trigger_interrupt()
108+
{
109+
get_flag().store(true);
110+
}
111+
112+
private:
113+
// Helper to access the singleton atomic flag safely
114+
static std::atomic<bool>& get_flag()
115+
{
116+
static std::atomic<bool> flag(false);
117+
return flag;
118+
}
119+
};
120+
72121
// ----------------------------------------------------------------------------------------
73122

74123
}

examples/slm_advanced_train_ex.cpp

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <dlib/data_io.h>
4242
#include <dlib/cmd_line_parser.h>
4343
#include <dlib/tokenizer/bpe_tokenizer.h>
44+
#include <dlib/misc_api.h>
4445

4546
// Include internal dataset
4647
#include "slm_data.h"
@@ -115,39 +116,6 @@ namespace dlib
115116
};
116117
}
117118

118-
// Signal handling for clean termination
119-
namespace {
120-
std::atomic<bool> g_terminate_flag(false);
121-
122-
#ifdef _WIN32
123-
// Windows-specific handler
124-
BOOL WINAPI console_ctrl_handler(DWORD ctrl_type) {
125-
if (ctrl_type == CTRL_C_EVENT) {
126-
g_terminate_flag.store(true);
127-
cout << "\nCtrl+C detected, cleaning up and closing the program..." << endl;
128-
return TRUE;
129-
}
130-
return FALSE;
131-
}
132-
133-
void setup_interrupt_handler() {
134-
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
135-
}
136-
#else
137-
// Unix/Linux-specific handler
138-
void signal_handler(int signal) {
139-
if (signal == SIGINT) {
140-
g_terminate_flag.store(true);
141-
cout << "\nCtrl+C detected, cleaning up and closing the program..." << endl;
142-
}
143-
}
144-
145-
void setup_interrupt_handler() {
146-
std::signal(SIGINT, signal_handler);
147-
}
148-
#endif
149-
}
150-
151119
// Utility functions
152120
std::string generate_tokens_filename(size_t max_bytes)
153121
{
@@ -252,7 +220,7 @@ int main(int argc, char** argv)
252220
try
253221
{
254222
// Setup interrupt handling for clean termination
255-
setup_interrupt_handler();
223+
signal_handler::setup();
256224

257225
command_line_parser parser;
258226
parser.add_option("train", "Train a transformer model on internal dataset");
@@ -450,7 +418,6 @@ int main(int argc, char** argv)
450418
using net_type = my_transformer::network_type<true>;
451419
net_type net;
452420
const int pad_token = tokenizer.get_special_token_id("<pad>");
453-
layer<0>(net).loss_details().set_ignore_index(pad_token);
454421
cout << my_transformer::model_info::describe() << endl;
455422

456423
// Tokenizer stored with model for simplified inference
@@ -475,7 +442,8 @@ int main(int argc, char** argv)
475442
auto epoch_start = std::chrono::high_resolution_clock::now();
476443

477444
// Training loop
478-
while (trainer.get_learning_rate() >= 1e-6 && epoch < max_epochs && !g_terminate_flag.load())
445+
while (trainer.get_learning_rate() >= 1e-6 && epoch < max_epochs
446+
&& !signal_handler::is_triggered())
479447
{
480448
total_loss = 0.0;
481449
batches_seen = samples_seen = 0;
@@ -484,7 +452,7 @@ int main(int argc, char** argv)
484452
// Shuffle the dataset
485453
shuffle_training_dataset(samples, labels);
486454

487-
for (size_t i = 0; i < samples.size() && !g_terminate_flag.load(); i += batch_size)
455+
for (size_t i = 0; i < samples.size() && !signal_handler::is_triggered(); i += batch_size)
488456
{
489457
size_t batch_end = std::min(i + batch_size, samples.size());
490458
std::vector<matrix<int, 0, 1>> batch_samples(
@@ -529,7 +497,7 @@ int main(int argc, char** argv)
529497

530498
// Evaluate on training set
531499
{
532-
if (!g_terminate_flag.load()) {
500+
if (!signal_handler::is_triggered()) {
533501
cout << "Evaluating model accuracy...\n";
534502
my_transformer::network_type<false> g_infer;
535503
deserialize(model_file) >> g_infer >> tokenizer;
@@ -665,7 +633,8 @@ int main(int argc, char** argv)
665633

666634
// Generate until target size is reached
667635
int end_of_text = tokenizer.get_special_token_id("</text>"), next_token = 0;
668-
while (total_bytes < target_size && next_token != end_of_text && !g_terminate_flag.load()) {
636+
while (total_bytes < target_size && next_token != end_of_text
637+
&& !signal_handler::is_triggered()) {
669638
// Predict next token
670639
long pad_len = count_leading_padding(input_seq, pad_token);
671640
tril_padding_context::set_uniform(pad_len, 1);

0 commit comments

Comments
 (0)