@@ -527,3 +527,89 @@ def test_full_pass(self, sub_factory, monkeypatch, tmp_tle):
527527 assert snd_msg .data == expected_msg .data
528528 finally :
529529 gatherer .stop ()
530+
531+
532+ def test_sigterm (tmp_config_file , tmp_config_parser ):
533+ """Test that SIGTERM signal is handled."""
534+ import os
535+ import signal
536+ import time
537+ from multiprocessing import Process
538+
539+ from pytroll_collectors .geographic_gatherer import GeographicGatherer
540+
541+ with open (tmp_config_file , mode = "w" ) as fp :
542+ tmp_config_parser .write (fp )
543+
544+ opts = arg_parse (["-c" , "minimal_config" , "-p" , "40000" , "-n" , "false" , "-i" , "localhost:12345" ,
545+ str (tmp_config_file )])
546+ # We don't need the triggers here. They also interfere with completing the test (the test never exits)
547+ with patch ("pytroll_collectors.geographic_gatherer.TriggerFactory.create" ):
548+ gatherer = GeographicGatherer (opts )
549+ proc = Process (target = gatherer .run )
550+ proc .start ()
551+ time .sleep (1 )
552+ os .kill (proc .pid , signal .SIGTERM )
553+ proc .join ()
554+
555+ assert proc .exitcode == 0
556+
557+
558+ def test_sigterm_with_collection (tmp_config_file , tmp_config_parser ):
559+ """Test that SIGTERM signal is handled when there is collection ongoing."""
560+ import os
561+ import signal
562+ import time
563+ from multiprocessing import Process
564+
565+ from pytroll_collectors .geographic_gatherer import GeographicGatherer
566+
567+ with open (tmp_config_file , mode = "w" ) as fp :
568+ tmp_config_parser .write (fp )
569+
570+ opts = arg_parse (["-c" , "posttroll_section" , "-p" , "40000" , "-n" , "false" , "-i" , "localhost:12345" ,
571+ str (tmp_config_file )])
572+ # Use a fake trigger that initially sets some granules and after a while clears them
573+ with patch ("pytroll_collectors.geographic_gatherer.PostTrollTrigger" ,
574+ new = FakeTriggerWithGranules ):
575+ gatherer = GeographicGatherer (opts )
576+ proc = Process (target = gatherer .run )
577+ proc .start ()
578+ time .sleep (1 )
579+ os .kill (proc .pid , signal .SIGTERM )
580+ proc .join ()
581+
582+ assert proc .exitcode == 0
583+
584+
585+ class FakeTriggerWithGranules :
586+ """Fake trigger class used in testing SIGTERM handling.
587+
588+ At creation, adds "foo" to collector granules. When is_alive() is called the second time, it clears the granules.
589+ """
590+
591+ def __init__ (self , collectors , * args , ** kwargs ):
592+ """Initialize the trigger class."""
593+ self .collectors = collectors
594+ for col in self .collectors :
595+ col .granules .append ("foo" )
596+ self ._args = args
597+ self ._kwargs = kwargs
598+ self ._counter = 0
599+
600+ def is_alive (self ):
601+ """Return True for alive thread."""
602+ if self ._counter > 0 :
603+ # On the second call clear the granules
604+ for col in self .collectors :
605+ col .granules = []
606+ self ._counter += 1
607+ return True
608+
609+ def start (self ):
610+ """Start the trigger."""
611+ pass
612+
613+ def stop (self ):
614+ """Stop the trigger."""
615+ pass
0 commit comments