2424#include < signal.h>
2525#endif
2626
27- static bool g_is_generating = false ;
27+ // volatile, because of signal being an interrupt
28+ static volatile bool g_is_generating = false ;
29+ static volatile bool is_app_running = true ;
2830
2931/* *
3032 * Please note that this is NOT a production-ready stuff.
@@ -50,8 +52,10 @@ static void sigint_handler(int signo) {
5052 g_is_generating = false ;
5153 } else {
5254 console::cleanup ();
53- LOG (" \n Interrupted by user\n " );
54- _exit (130 );
55+ if (!is_app_running) {
56+ _exit (1 );
57+ }
58+ is_app_running = false ;
5559 }
5660 }
5761}
@@ -167,7 +171,7 @@ struct decode_embd_batch {
167171static int generate_response (mtmd_cli_context & ctx, common_sampler * smpl, int n_predict) {
168172 llama_tokens generated_tokens;
169173 for (int i = 0 ; i < n_predict; i++) {
170- if (i > n_predict || !g_is_generating) {
174+ if (i > n_predict || !g_is_generating || !is_app_running ) {
171175 printf (" \n " );
172176 break ;
173177 }
@@ -184,6 +188,11 @@ static int generate_response(mtmd_cli_context & ctx, common_sampler * smpl, int
184188 printf (" %s" , common_token_to_piece (ctx.lctx , token_id).c_str ());
185189 fflush (stdout);
186190
191+ if (!is_app_running) {
192+ printf (" \n " );
193+ break ;
194+ }
195+
187196 // eval the token
188197 common_batch_clear (ctx.batch );
189198 common_batch_add (ctx.batch , token_id, ctx.n_past ++, {0 }, true );
@@ -206,6 +215,7 @@ static int eval_message(mtmd_cli_context & ctx, common_chat_msg & msg, std::vect
206215 LOG_DBG (" formatted_chat.prompt: %s\n " , formatted_chat.prompt .c_str ());
207216
208217 for (auto & fname : images_fname) {
218+ if (!is_app_running) return 0 ;
209219 mtmd_bitmap bitmap;
210220 if (mtmd_helper_bitmap_init_from_file (fname.c_str (), bitmap)) {
211221 LOG_ERR (" Unable to load image %s\n " , fname.c_str ());
@@ -219,6 +229,9 @@ static int eval_message(mtmd_cli_context & ctx, common_chat_msg & msg, std::vect
219229 text.add_special = add_bos;
220230 text.parse_special = true ;
221231 mtmd_input_chunks chunks;
232+
233+ if (!is_app_running) return 0 ;
234+
222235 int32_t res = mtmd_tokenize (ctx.ctx_vision .get (), chunks, text, bitmaps);
223236 if (res != 0 ) {
224237 LOG_ERR (" Unable to tokenize prompt, res = %d\n " , res);
@@ -276,6 +289,8 @@ int main(int argc, char ** argv) {
276289#endif
277290 }
278291
292+ if (!is_app_running) return 130 ;
293+
279294 if (is_single_turn) {
280295 g_is_generating = true ;
281296 if (params.prompt .find (" <__image__>" ) == std::string::npos) {
@@ -287,7 +302,7 @@ int main(int argc, char ** argv) {
287302 if (eval_message (ctx, msg, params.image , true )) {
288303 return 1 ;
289304 }
290- if (generate_response (ctx, smpl, n_predict)) {
305+ if (is_app_running && generate_response (ctx, smpl, n_predict)) {
291306 return 1 ;
292307 }
293308
@@ -302,12 +317,13 @@ int main(int argc, char ** argv) {
302317 std::vector<std::string> images_fname;
303318 std::string content;
304319
305- while (true ) {
320+ while (is_app_running ) {
306321 g_is_generating = false ;
307322 LOG (" \n > " );
308323 console::set_display (console::user_input);
309324 std::string line;
310325 console::readline (line, false );
326+ if (!is_app_running) break ;
311327 console::set_display (console::reset);
312328 line = string_strip (line);
313329 if (line.empty ()) {
@@ -335,6 +351,7 @@ int main(int argc, char ** argv) {
335351 msg.role = " user" ;
336352 msg.content = content;
337353 int ret = eval_message (ctx, msg, images_fname, is_first_msg);
354+ if (!is_app_running) break ;
338355 if (ret == 2 ) {
339356 // non-fatal error
340357 images_fname.clear ();
@@ -352,6 +369,7 @@ int main(int argc, char ** argv) {
352369 is_first_msg = false ;
353370 }
354371 }
372+ if (!is_app_running) LOG (" \n Interrupted by user\n " );
355373 llama_perf_context_print (ctx.lctx );
356- return 0 ;
374+ return is_app_running ? 0 : 130 ;
357375}
0 commit comments