@@ -37,6 +37,8 @@ struct acrnd_work {
37
37
static LIST_HEAD (acrnd_work_list , acrnd_work ) work_head ;
38
38
static pthread_mutex_t work_mutex = PTHREAD_MUTEX_INITIALIZER ;
39
39
40
+ static pthread_mutex_t acrnd_stop_mutex = PTHREAD_MUTEX_INITIALIZER ;
41
+ static unsigned int acrnd_stop_timeout ;
40
42
/* acrnd_add_work(), add a worker function.
41
43
* @func, the worker function.
42
44
* @sec, when add a @func(), after @sec seconds @func() will be called.
@@ -412,7 +414,7 @@ static int check_vms_status(unsigned int status)
412
414
return 0 ;
413
415
}
414
416
415
- static int _handle_acrnd_stop (unsigned int timeout )
417
+ static int wait_for_stop (unsigned int timeout )
416
418
{
417
419
unsigned long t = timeout ;
418
420
@@ -421,26 +423,107 @@ static int _handle_acrnd_stop(unsigned int timeout)
421
423
/* list and update the vm status */
422
424
do {
423
425
if (check_vms_status (VM_CREATED ) == 0 )
424
- return 0 ;
426
+ return SHUTDOWN ;
427
+
428
+ if (check_vms_status (VM_PAUSED ) == 0 )
429
+ return SUSPEND ;
430
+
425
431
sleep (1 );
426
432
}
427
433
while (t -- );
428
434
429
435
return -1 ;
430
436
}
431
437
438
+ static void * notify_stop_state (void * arg )
439
+ {
440
+ int lcs_fd ;
441
+ int rc ;
442
+ struct mngr_msg req ;
443
+
444
+ req .magic = MNGR_MSG_MAGIC ;
445
+
446
+ rc = wait_for_stop (acrnd_stop_timeout );
447
+ if (rc < 0 ) {
448
+ fprintf (stderr , "cannot get VMs stop state\n" );
449
+ req .msgid = SUSPEND ;
450
+ req .data .err = -1 ;
451
+ } else {
452
+ req .msgid = rc ;
453
+ req .data .err = 0 ;
454
+ }
455
+
456
+ store_timer_list ();
457
+
458
+ lcs_fd = mngr_open_un (SOS_LCS_SOCK , MNGR_CLIENT );
459
+ if (lcs_fd < 0 ) {
460
+ fprintf (stderr , "cannot open sos-lcs.socket\n" );
461
+ goto exit ;
462
+ }
463
+
464
+ mngr_send_msg (lcs_fd , & req , NULL , 0 );
465
+ mngr_close (lcs_fd );
466
+ exit :
467
+ pthread_mutex_unlock (& acrnd_stop_mutex );
468
+ return NULL ;
469
+ }
470
+
471
+ static void _handle_acrnd_stop (unsigned int timeout )
472
+ {
473
+ int rc ;
474
+ pthread_t tid ;
475
+ pthread_attr_t attr ;
476
+
477
+ /*
478
+ * Only one acrnd stop thread at a time
479
+ * if failed to lock the acrnd_stop_mutex, then return directly
480
+ * if creating thread success, then unlock in the thread exit
481
+ * if failed to create thread, then unlock immediately.
482
+ */
483
+ if (pthread_mutex_trylock (& acrnd_stop_mutex ) == 0 ) {
484
+
485
+ acrnd_stop_timeout = timeout ;
486
+
487
+ /*
488
+ * Due to acrnd only has one main thread, and acrnd stop flow
489
+ * probably blocks main thread, so a detached thread is created
490
+ * to avoid this.
491
+ */
492
+ rc = pthread_attr_init (& attr );
493
+ if (rc < 0 )
494
+ goto fail_init ;
495
+ rc = pthread_attr_setdetachstate (& attr ,
496
+ PTHREAD_CREATE_DETACHED );
497
+ if (rc < 0 )
498
+ goto fail ;
499
+ rc = pthread_create (& tid , & attr , notify_stop_state , NULL );
500
+ if (rc < 0 )
501
+ goto fail ;
502
+
503
+ pthread_attr_destroy (& attr );
504
+ }
505
+
506
+ return ;
507
+
508
+ fail :
509
+ pthread_attr_destroy (& attr );
510
+
511
+ fail_init :
512
+ pthread_mutex_unlock (& acrnd_stop_mutex );
513
+ fprintf (stderr , "Failed to invoke handle_acrnd_stop \n" );
514
+ }
515
+
432
516
static void handle_acrnd_stop (struct mngr_msg * msg , int client_fd , void * param )
433
517
{
434
518
struct mngr_msg ack ;
435
519
436
520
ack .msgid = msg -> msgid ;
437
521
ack .timestamp = msg -> timestamp ;
438
- ack .data .err = _handle_acrnd_stop (msg -> data .acrnd_stop .timeout );
439
-
440
- store_timer_list ();
441
-
522
+ ack .data .err = 0 ;
442
523
if (client_fd > 0 )
443
524
mngr_send_msg (client_fd , & ack , NULL , 0 );
525
+
526
+ _handle_acrnd_stop (msg -> data .acrnd_stop .timeout );
444
527
}
445
528
446
529
void handle_acrnd_resume (struct mngr_msg * msg , int client_fd , void * param )
0 commit comments