4444)
4545from opentelemetry .sdk .resources import Resource as SDKResource
4646from opentelemetry .sdk .util .instrumentation import InstrumentationScope
47+ from opentelemetry .test .concurrency_test import ConcurrencyTestBase
4748from opentelemetry .trace import TraceFlags
4849from opentelemetry .trace .span import INVALID_SPAN_CONTEXT
4950
@@ -559,7 +560,7 @@ def bulk_log_and_flush(num_logs):
559560 hasattr (os , "fork" ),
560561 "needs *nix" ,
561562 )
562- def test_batch_log_record_processor_fork (self ):
563+ def test_batch_log_record_processor_fork_clears_logs_from_child (self ):
563564 exporter = InMemoryLogExporter ()
564565 log_record_processor = BatchLogRecordProcessor (
565566 exporter ,
@@ -572,15 +573,13 @@ def test_batch_log_record_processor_fork(self):
572573 for _ in range (10 ):
573574 log_record_processor .emit (EMPTY_LOG )
574575
576+ # The below test also needs this, but it can only be set once.
575577 multiprocessing .set_start_method ("fork" )
576578
577579 def child (conn ):
578- for _ in range (100 ):
579- log_record_processor .emit (EMPTY_LOG )
580580 log_record_processor .force_flush ()
581-
582581 logs = exporter .get_finished_logs ()
583- conn .send (len (logs ) == 100 )
582+ conn .send (len (logs ) == 0 )
584583 conn .close ()
585584
586585 parent_conn , child_conn = multiprocessing .Pipe ()
@@ -591,6 +590,34 @@ def child(conn):
591590 log_record_processor .force_flush ()
592591 self .assertTrue (len (exporter .get_finished_logs ()) == 10 )
593592
593+ @unittest .skipUnless (
594+ hasattr (os , "fork" ),
595+ "needs *nix" ,
596+ )
597+ def test_batch_log_record_processor_fork_doesnot_deadlock (self ):
598+ exporter = InMemoryLogExporter ()
599+ log_record_processor = BatchLogRecordProcessor (
600+ exporter ,
601+ max_export_batch_size = 64 ,
602+ schedule_delay_millis = 30000 ,
603+ )
604+
605+ def child (conn ):
606+ def _target ():
607+ log_record_processor .emit (EMPTY_LOG )
608+
609+ ConcurrencyTestBase .run_with_many_threads (_target , 100 )
610+ log_record_processor .force_flush ()
611+ logs = exporter .get_finished_logs ()
612+ conn .send (len (logs ) == 100 )
613+ conn .close ()
614+
615+ parent_conn , child_conn = multiprocessing .Pipe ()
616+ process = multiprocessing .Process (target = child , args = (child_conn ,))
617+ process .start ()
618+ self .assertTrue (parent_conn .recv ())
619+ process .join ()
620+
594621
595622class TestConsoleLogExporter (unittest .TestCase ):
596623 def test_export (self ): # pylint: disable=no-self-use
0 commit comments