in src/agent/src/main.c [902:1111]
int main(int argc, char** argv)
{
ADUC_LaunchArguments launchArgs;
InitializeModeledComponents();
int ret = ParseLaunchArguments(argc, argv, &launchArgs);
if (ret < 0)
{
return ret;
}
if (launchArgs.showVersion)
{
puts(ADUC_VERSION);
return 0;
}
// Need to set ret and goto done after this to ensure proper shutdown and deinitialization.
ADUC_Logging_Init(launchArgs.logLevel, "du-agent");
ADUCPAL_setenv(ADUC_CONFIG_FOLDER_ENV, launchArgs.configFolder, 1);
const ADUC_ConfigInfo* config = ADUC_ConfigInfo_GetInstance();
if (config == NULL)
{
Log_Error("Cannot initialize config info.");
return -1;
}
// default to failure
ret = 1;
if (launchArgs.healthCheckOnly)
{
if (HealthCheck(&launchArgs))
{
ret = 0;
}
goto done;
}
if (launchArgs.extensionFilePath != NULL)
{
switch (launchArgs.extensionRegistrationType)
{
case ExtensionRegistrationType_None:
Log_Error("Missing --extension-type argument.");
goto done;
case ExtensionRegistrationType_UpdateContentHandler:
if (launchArgs.extensionId == NULL)
{
Log_Error("Missing --extension-id argument.");
goto done;
}
if (RegisterUpdateContentHandler(launchArgs.extensionId, launchArgs.extensionFilePath))
{
ret = 0;
}
goto done;
case ExtensionRegistrationType_ComponentEnumerator:
if (RegisterComponentEnumeratorExtension(launchArgs.extensionFilePath))
{
ret = 0;
}
goto done;
case ExtensionRegistrationType_ContentDownloadHandler:
if (RegisterContentDownloaderExtension(launchArgs.extensionFilePath))
{
ret = 0;
}
goto done;
case ExtensionRegistrationType_DownloadHandler:
if (launchArgs.extensionId == NULL)
{
Log_Error("Missing --extension-id argument.");
goto done;
}
if (RegisterDownloadHandler(launchArgs.extensionId, launchArgs.extensionFilePath))
{
ret = 0;
}
goto done;
default:
Log_Error("Unknown ExtensionRegistrationType: %d", launchArgs.extensionRegistrationType);
goto done;
}
}
#ifdef ADUC_COMMAND_HELPER_H
// This instance of an agent is launched for sending command to the main agent process.
if (launchArgs.ipcCommand != NULL)
{
if (SendCommand(launchArgs.ipcCommand))
{
ret = 0;
}
goto done;
}
#endif // #ifdef ADUC_COMMAND_HELPER_H
// Switch to specified agent.runas user.
// Note: it's important that we do this only when we're not performing any
// high-privileged tasks, such as, registering agent's extension(s).
if (!RunAsDesiredUser())
{
goto done;
}
Log_Info("Agent (%s; %s) starting.", ADUC_PLATFORM_LAYER, ADUC_VERSION);
#ifdef ADUC_GIT_INFO
Log_Info("Git Info: %s", ADUC_GIT_INFO);
#endif
Log_Info(
"Supported Update Manifest version: min: %d, max: %d",
SUPPORTED_UPDATE_MANIFEST_VERSION_MIN,
SUPPORTED_UPDATE_MANIFEST_VERSION_MAX);
bool healthy = HealthCheck(&launchArgs);
if (launchArgs.healthCheckOnly || !healthy)
{
if (healthy)
{
Log_Info("Agent is healthy.");
ret = 0;
}
else
{
Log_Error("Agent health check failed.");
}
goto done;
}
// Ensure that the ADU data folder exists.
// Normally, ADUC_DATA_FOLDER is created by install script.
// However, if we want to run the Agent without installing the package, we need to manually
// create the folder. (e.g. when running UTs in build pipelines, side-loading for testing, etc.)
int dir_result = ADUC_SystemUtils_MkDirRecursiveDefault(ADUC_DATA_FOLDER);
if (dir_result != 0)
{
Log_Error("Cannot create data folder.");
goto done;
}
//
// Catch ctrl-C and shutdown signals so we do a best effort of cleanup.
//
signal(SIGINT, OnShutdownSignal);
signal(SIGTERM, OnShutdownSignal);
if (!StartupAgent(&launchArgs))
{
goto done;
}
//
// Main Loop
//
Log_Info("Agent running.");
while (ADUC_ShutdownService_ShouldKeepRunning())
{
// If any components have requested a DoWork callback, regularly call it.
for (unsigned index = 0; index < ARRAY_SIZE(componentList); ++index)
{
PnPComponentEntry* entry = componentList + index;
if (entry->DoWork != NULL)
{
entry->DoWork(entry->Context);
}
}
IoTHub_CommunicationManager_DoWork(&g_iotHubClientHandle);
ADUC_D2C_Messaging_DoWork();
// NOTE: When using low level samples (iothub_ll_*), the IoTHubDeviceClient_LL_DoWork
// function must be called regularly (eg. every 100 milliseconds) for the IoT device client to work properly.
// See: https://github.com/Azure/azure-iot-sdk-c/tree/master/iothub_client/samples
// NOTE: For this example the above has been wrapped to support module and device client methods using
// the client_handle_helper.h function ClientHandle_DoWork()
ThreadAPI_Sleep(100);
};
ret = 0; // Success.
done:
Log_Info("Agent exited with code %d", ret);
ShutdownAgent();
ADUC_ConfigInfo_ReleaseInstance(config);
return ret;
}