Skip to content

Commit

Permalink
Fix SimulatedTemperatureSensor Module Status Issues on Stop command (#…
Browse files Browse the repository at this point in the history
…7420)

Issue description:
**Expected Behavior**
When changing the module status from Running to Stopped via the Azure portal, the module on the device should stop successfully.

**Actual Behavior**
After setting the module to Stopped, running sudo iotedge list shows the SimulatedTemperatureSensor module in a Failed (139) state instead of Stopped.

**Fix: **
This pull request addresses the issues causing the SimulatedTemperatureSensor module to fail with exit code 139 when it receives a stop command from the Azure portal.

Initially, the SimulatedTemperatureSensor module encountered exit code 139 due to improper handling of task cancellations, leading to a segmentation fault. To address this, handling for TaskCanceledException was added in the SendEvents method to log a message when the task is canceled.

Changes made:
- Added handling for TaskCanceledException in the SendEvents method to log a message when the task is canceled.
- Setting the Environment.ExitCode to 0 indicating the successful exit.
- Replacing the Console statements with logger.
These changes address the issues causing the SimulatedTemperatureSensor module to fail with exit codes 139 and 143, ensuring the module transitions to the stopped state correctly.
![image](https://github.com/user-attachments/assets/a3f3bfeb-8b31-4392-9133-7801e94cb3f5)


## Azure IoT Edge PR checklist:
  • Loading branch information
sush-101 authored Feb 24, 2025
1 parent 03cd85d commit 8c5625d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
"machinePressureMin": 1,
"machinePressureMax": 10,
"ambientTemp": 21,
"ambientHumidity": 25
"ambientHumidity": 25,
"RuntimeLogLevel": "info"
}
53 changes: 41 additions & 12 deletions edge-modules/SimulatedTemperatureSensor/src/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ namespace SimulatedTemperatureSensor
using Microsoft.Azure.Devices.Edge.Util.TransientFaultHandling;
using Microsoft.Azure.Devices.Shared;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using ExponentialBackoff = Microsoft.Azure.Devices.Edge.Util.TransientFaultHandling.ExponentialBackoff;

Expand All @@ -39,6 +40,7 @@ class Program
static TimeSpan messageDelay;
static bool sendData = true;

static ILogger logger = null;
public enum ControlCommandEnum
{
Reset = 0,
Expand All @@ -49,14 +51,15 @@ public enum ControlCommandEnum

static async Task<int> MainAsync()
{
Console.WriteLine("SimulatedTemperatureSensor Main() started.");
Console.WriteLine($"{DateTime.UtcNow.ToLogString()} SimulatedTemperatureSensor Main() started.");

IConfiguration configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("config/appsettings.json", optional: true)
.AddEnvironmentVariables()
.Build();

logger = SetupLogger(configuration);
messageDelay = configuration.GetValue("MessageDelay", TimeSpan.FromSeconds(5));
int messageCount = configuration.GetValue(MessageCountConfigKey, 500);
var simulatorParameters = new SimulatorParameters
Expand All @@ -69,7 +72,7 @@ static async Task<int> MainAsync()
HumidityPercent = configuration.GetValue("ambientHumidity", 25)
};

Console.WriteLine(
logger.LogInformation(
$"Initializing simulated temperature sensor to send {(SendUnlimitedMessages(messageCount) ? "unlimited" : messageCount.ToString())} "
+ $"messages, at an interval of {messageDelay.TotalSeconds} seconds.\n"
+ $"To change this, set the environment variable {MessageCountConfigKey} to the number of messages that should be sent (set it to -1 to send unlimited messages).");
Expand All @@ -83,7 +86,7 @@ static async Task<int> MainAsync()
await moduleClient.OpenAsync();
await moduleClient.SetMethodHandlerAsync("reset", ResetMethod, null);

(CancellationTokenSource cts, ManualResetEventSlim completed, Option<object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), null);
(CancellationTokenSource cts, ManualResetEventSlim completed, Option<object> handler) = ShutdownHandler.Init(TimeSpan.FromSeconds(5), logger);

Twin currentTwinProperties = await moduleClient.GetTwinAsync();
if (currentTwinProperties.Properties.Desired.Contains(SendIntervalConfigKey))
Expand All @@ -96,7 +99,7 @@ static async Task<int> MainAsync()
sendData = (bool)currentTwinProperties.Properties.Desired[SendDataConfigKey];
if (!sendData)
{
Console.WriteLine("Sending data disabled. Change twin configuration to start sending again.");
logger.LogInformation("Sending data disabled. Change twin configuration to start sending again.");
}
}

Expand All @@ -106,12 +109,22 @@ static async Task<int> MainAsync()
await SendEvents(moduleClient, messageCount, simulatorParameters, cts);
await cts.Token.WhenCanceled();

await moduleClient?.CloseAsync();
moduleClient?.Dispose();
completed.Set();
handler.ForEach(h => GC.KeepAlive(h));
Console.WriteLine("SimulatedTemperatureSensor Main() finished.");
logger.LogInformation("SimulatedTemperatureSensor Main() finished.");
return 0;
}

static ILogger SetupLogger(IConfiguration configuration)
{
string logLevel = configuration.GetValue($"{Logger.RuntimeLogLevelEnvKey}", "info");
Logger.SetLogLevel(logLevel);
ILogger logger = Logger.Factory.CreateLogger<Program>();
return logger;
}

static bool SendUnlimitedMessages(int maximumNumberOfMessages) => maximumNumberOfMessages < 0;

// Control Message expected to be:
Expand Down Expand Up @@ -224,18 +237,34 @@ static async Task SendEvents(
eventMessage.ContentType = "application/json";
eventMessage.Properties.Add("sequenceNumber", count.ToString());
eventMessage.Properties.Add("batchId", BatchId.ToString());
Console.WriteLine($"\t{DateTime.Now.ToLocalTime()}> Sending message: {count}, Body: [{dataBuffer}]");
logger.LogInformation($"Sending message: {count}, Body: [{dataBuffer}]");
try
{
await moduleClient.SendEventAsync("temperatureOutput", eventMessage, cts.Token);
}
catch (OperationCanceledException)
{
logger.LogError($"SendEvents has been canceled, sent {count - 1} messages.");
return;
}

await moduleClient.SendEventAsync("temperatureOutput", eventMessage);
count++;
}

await Task.Delay(messageDelay, cts.Token);
try
{
await Task.Delay(messageDelay, cts.Token);
}
catch (TaskCanceledException)
{
logger.LogError($"SendEvents has been canceled, sent {count - 1} messages.");
return;
}
}

if (messageCount < count)
{
Console.WriteLine($"Done sending {messageCount} messages");
logger.LogInformation($"Done sending {messageCount} messages");
}
}

Expand Down Expand Up @@ -269,7 +298,7 @@ static async Task<ModuleClient> CreateModuleClientAsync(
RetryStrategy retryStrategy = null)
{
var retryPolicy = new RetryPolicy(transientErrorDetectionStrategy, retryStrategy);
retryPolicy.Retrying += (_, args) => { Console.WriteLine($"[Error] Retry {args.CurrentRetryCount} times to create module client and failed with exception:{Environment.NewLine}{args.LastException}"); };
retryPolicy.Retrying += (_, args) => { logger.LogError($"Retry {args.CurrentRetryCount} times to create module client and failed with exception:{Environment.NewLine}{args.LastException}"); };

ModuleClient client = await retryPolicy.ExecuteAsync(
async () =>
Expand All @@ -291,11 +320,11 @@ ITransportSettings[] GetTransportSettings()
}

ITransportSettings[] settings = GetTransportSettings();
Console.WriteLine($"[Information]: Trying to initialize module client using transport type [{transportType}].");
logger.LogInformation($"Trying to initialize module client using transport type [{transportType}].");
ModuleClient moduleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
await moduleClient.OpenAsync();

Console.WriteLine($"[Information]: Successfully initialized module client of transport type [{transportType}].");
logger.LogInformation($"Successfully initialized module client of transport type [{transportType}].");
return moduleClient;
});

Expand Down

0 comments on commit 8c5625d

Please sign in to comment.