Server media event and signal handling

event type

Generally speaking, the purpose of dividing events is to register various events in the script, so as to notify other modules and executable files of various abnormal and non-abnormal occurrence points. For example, a client link is a non-abnormal occurrence point. Timeout offline is an exception point.

The clear division of events in the structure makes it easier to organize the process clearly. Events can be divided into
1 service event
2 session event
3 service status event, such as recording start

switch(_type)
		{
    
    
			// StreamEventType
			case EventType::ServerStarted:
			case EventType::HostCreated:
			case EventType::HostDeleted:
			case EventType::AppCreated:
			case EventType::AppDeleted:
			case EventType::StreamCreated:
			case EventType::StreamDeleted: 
			case EventType::StreamOriginLinkUpdated:
			case EventType::StreamOutputsUpdated:
				_category = EventCategory::StreamEventType;
				break;
			// SessionEventType
			case EventType::SessionConnected:
			case EventType::SessionDisconnected:
				_category = EventCategory::SessionEventType;
				break;
			// ActoinEventType
			case EventType::ApiCalled:
			case EventType::RecordingStarted:
			case EventType::RecordingStopped:
			case EventType::PushStarted:
			case EventType::PushStopped:
				_category = EventCategory::ActoinEventType;
				break;
			// NotificationEventType
			case EventType::Info:
			case EventType::Error:
				_category = EventCategory::NotificationEventType;
				break;
			// StatisticsEventType
			case EventType::ServerStat:
				_category = EventCategory::StatisticsEventType;
				break;
		}

event translation

Translate events into recognizable strings

String Event::GetTypeString() const
	{
    
    
		switch(_type)
		{
    
    
			// StreamEventType
			case EventType::ServerStarted:
				return "ServerStarted";
			case EventType::HostCreated:
				return "HostCreated";
			case EventType::HostDeleted:
				return "HostDeleted";
			case EventType::AppCreated:
				return "AppCreated";
			case EventType::AppDeleted:
				return "AppDeleted";
			case EventType::StreamCreated:
				return "StreamCreated";
			case EventType::StreamDeleted: 
				return "StreamDeleted";
			case EventType::StreamOriginLinkUpdated:
				return "StreamOriginLinkUpdated";
			case EventType::StreamOutputsUpdated:
				return "StreamOutputsUpdated";
			// SessionEventType
			case EventType::SessionConnected:
				return "SessionConnected";
			case EventType::SessionDisconnected:
				return "SessionDisconnected";
			// ActoinEventType
			case EventType::ApiCalled:
				return "ApiCalled";
			case EventType::RecordingStarted:
				return "RecordingStarted";
			case EventType::RecordingStopped:
				return "RecordingStopped";
			case EventType::PushStarted:
				return "PushStarted";
			case EventType::PushStopped:
				return "PushStopped";
			// NotificationEventType
			case EventType::Info:
				return "Info";
			case EventType::Error:
				return "Error";
			// StatisticsEventType
			case EventType::ServerStat:
				return "ServerStat";
		}

		return "";
	}

Events are translated into json

For communication interpretation, events can be translated into json, as shown in the following code

String Event::SerializeToJson() const
	{
    
    
		Json::Value json_root;

		// Fill common values
		json_root["eventVersion"] = EVENT_VERSION;
		json_root["timestampMillis"] = _creation_time_msec;
		json_root["userKey"] = _server_metric->GetConfig()->GetAnalytics().GetUserKey().CStr();
		json_root["serverID"] = _server_metric->GetConfig()->GetID().CStr();
		
		// Fill root["event"]
		Json::Value &json_event = json_root["event"];
		json_event["type"] = GetTypeString().CStr();
		if(_message.IsEmpty() == false)
		{
    
    
			json_event["message"] = _message.CStr();
		}
		
		Json::Value &json_producer = json_event["producer"];
		FillProducer(json_producer);

		// Fill root["data"]
		Json::Value &json_data = json_root["data"];

		if(_category == EventCategory::StreamEventType)
		{
    
    
			//TODO(Getroot): Implement this
			json_data["dataType"] = "Not Implemented";

			Json::Value &json_server_info = json_data["serverInfo"];
			FillServerInfo(json_server_info);
		}
		else if(_category == EventCategory::StatisticsEventType)
		{
    
    
			Json::Value &json_server_stat = json_data["serverStat"];
			FillServerStatistics(json_server_stat);
		}

		Json::StreamWriterBuilder builder;
		/* 
			Default StreamWriterBuilder settings

		  	(*settings)["commentStyle"] = "All";
			(*settings)["indentation"] = "\t";
			(*settings)["enableYAMLCompatibility"] = false;
			(*settings)["dropNullPlaceholders"] = false;
			(*settings)["useSpecialFloats"] = false;
			(*settings)["emitUTF8"] = false;
			(*settings)["precision"] = 17;
			(*settings)["precisionType"] = "significant";
		*/

		logtd("%s", json_root.toStyledString().c_str());

		builder["indentation"] = "";
		return Json::writeString(builder, json_root).c_str();
	}

signal processing

A signal is a software interrupt that provides a processing mechanism for asynchronous events, such as SIGCHLD, which represents a sub-process termination signal. After the sub-process terminates, the signal is captured and the sub-process exception information is processed.

SIGUSR1 SIGUSR2 Both are process-defined signals. These signals are for user-defined purposes. The kernel never sends them. The process can use these two signals for any purpose.

Next is more signal processing, as shown below, there are many signals

bool InitializeSignals()
{
    
    
	//	 1) SIGHUP		 2) SIGINT		 3) SIGQUIT		 4) SIGILL		 5) SIGTRAP
	//	 6) SIGABRT		 7) SIGBUS		 8) SIGFPE		 9) SIGKILL		10) SIGUSR1
	//	11) SIGSEGV		12) SIGUSR2		13) SIGPIPE		14) SIGALRM		15) SIGTERM
	//	16) SIGSTKFLT	17) SIGCHLD		18) SIGCONT		19) SIGSTOP		20) SIGTSTP
	//	21) SIGTTIN		22) SIGTTOU		23) SIGURG		24) SIGXCPU		25) SIGXFSZ
	//	26) SIGVTALRM	27) SIGPROF		28) SIGWINCH	29) SIGIO		30) SIGPWR
	//	31) SIGSYS		34) SIGRTMIN	35) SIGRTMIN+1	36) SIGRTMIN+2	37) SIGRTMIN+3
	//	38) SIGRTMIN+4	39) SIGRTMIN+5	40) SIGRTMIN+6	41) SIGRTMIN+7	42) SIGRTMIN+8
	//	43) SIGRTMIN+9	44) SIGRTMIN+10	45) SIGRTMIN+11	46) SIGRTMIN+12	47) SIGRTMIN+13
	//	48) SIGRTMIN+14	49) SIGRTMIN+15	50) SIGRTMAX-14	51) SIGRTMAX-13	52) SIGRTMAX-12
	//	53) SIGRTMAX-11	54) SIGRTMAX-10	55) SIGRTMAX-9	56) SIGRTMAX-8	57) SIGRTMAX-7
	//	58) SIGRTMAX-6	59) SIGRTMAX-5	60) SIGRTMAX-4	61) SIGRTMAX-3	62) SIGRTMAX-2
	//	63) SIGRTMAX-1	64) SIGRTMAX

	return InitializeAbortSignal() &&
		   InitializeUser1Signal() &&
		   InitializeReloadSignal() &&
		   InitializeTerminateSignal();
}

Example of a signal handler

#include <stdio.h>

static void sigint_handle(int signo)
{
    
    
    printf("............................");
    exit(EXIT_SUCCESS);
}

int main(void)
{
    
    
  if(signal(SIGINT, sigint_handle) == SIG_ERR){
    
    
     fprintf(stderr,"can not handle\n";
     exit(EXIT_FAILURE);
  }
  for(;;)
  {
    
    
     pause();
  }
  return 0;
}

Among them, SIGINT is to handle user input interrupt symbol events, such as debugging using ctrl+c, and pause is a system call function, which will suspend the program and know that there is a signal, and the signal is sent to the process by the kernel to wake up the system process. This requires readers to master more principles of the operating system.

Combining events and signals

In addition to writing scripts for processing, such as lua, or javascript, etc., you can also associate events with signals, process system-level calls, such as encountering SIGSEGV memory processing exceptions, SIGXCPU process resource limit and other signals, we receive these signals Then you can restart or close the program.

Guess you like

Origin blog.csdn.net/qianbo042311/article/details/127158666