Skip to content

Commit 194fbc0

Browse files
fix: some stability improvements
1 parent c135531 commit 194fbc0

File tree

10 files changed

+132
-76
lines changed

10 files changed

+132
-76
lines changed

components/esp32-javascript/esp32-javascript.c

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,13 @@ void jslog(log_level_t level, const char *msg, ...)
125125
}
126126
else
127127
{
128-
char *message = malloc(strlen(my_string) + 1);
128+
char *message = spiram_malloc(strlen(my_string) + 1); // gets freed in el_readAndFreeString
129+
if (message == NULL)
130+
{
131+
ESP_LOGE(tag, "No memory to log message. Aborting...");
132+
abort();
133+
}
134+
129135
strcpy(message, my_string);
130136

131137
js_event_t event;
@@ -189,7 +195,10 @@ void IRAM_ATTR el_fire_events(js_eventlist_t *events)
189195
{
190196
if (events->events_len > 0)
191197
{
192-
ESP_LOGD(tag, "Send %d events to queue...", events->events_len);
198+
// el_fire_events is called from ISR and logging leads to overflowing stack (sometimes)
199+
// e.g. in timer routines, because timer task has limited stack size. Discovered in
200+
// backtrace of ELF 00d57bf2ccbe7755
201+
// ESP_LOGD(tag, "Send %d events to queue...", events->events_len);
193202
int ret = xQueueSendFromISR(el_event_queue, events, NULL);
194203
if (ret != pdTRUE)
195204
{
@@ -223,7 +232,7 @@ void IRAM_ATTR vTimerCallback(TimerHandle_t xTimer)
223232
js_event_t event;
224233
js_eventlist_t events;
225234

226-
xTimerDelete(xTimer, portMAX_DELAY);
235+
xTimerDelete(xTimer, 0);
227236

228237
el_create_event(&event, EL_TIMER_EVENT_TYPE, (int)xTimer, 0);
229238
events.events_len = 0;
@@ -237,6 +246,12 @@ int createTimer(int timer_period_us)
237246

238247
TimerHandle_t tmr = xTimerCreate("", interval <= 0 ? 1 : interval, pdFALSE, NULL, vTimerCallback);
239248

249+
if (tmr == NULL)
250+
{
251+
jslog(ERROR, "Could not create timer.");
252+
abort();
253+
}
254+
240255
if (interval <= 0)
241256
{
242257
// fire event immediatley without starting the timer
@@ -424,15 +439,7 @@ static duk_ret_t el_suspend(duk_context *ctx)
424439
// force garbage collection 2 times see duktape doc
425440
// greatly increases perfomance with external memory
426441
duk_gc(ctx, 0);
427-
if (uxQueueMessagesWaiting(el_event_queue) == 0)
428-
{
429-
// if no event is waiting also compact heap
430-
duk_gc(ctx, DUK_GC_COMPACT);
431-
}
432-
else
433-
{
434-
duk_gc(ctx, 0);
435-
}
442+
duk_gc(ctx, 0);
436443

437444
while (xQueueReceive(el_event_queue, &events, timeout) == pdTRUE)
438445
{
@@ -844,7 +851,7 @@ duk_ret_t el_readAndFreeString(duk_context *ctx)
844851
{
845852
char *str = duk_to_int(ctx, 0);
846853
duk_push_string(ctx, str);
847-
free(str);
854+
spiram_free(str);
848855
return 1;
849856
}
850857

components/esp32-javascript/modules/esp32-javascript/http.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,10 +395,11 @@ errorCB, finishCB, dataCB, headCB) {
395395
}
396396
closeSocket(sockfd);
397397
}
398-
}, function () {
398+
}, function (sockfd) {
399399
if (errorCB) {
400400
errorCB("Could not load " + (ssl ? "https" : "http") + "://" + host + ":" + port + path);
401401
}
402+
closeSocket(sockfd);
402403
}, function () {
403404
if (finishCB) {
404405
finishCB();

components/esp32-javascript/modules/esp32-javascript/http.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,12 +515,13 @@ export function httpClient(
515515
closeSocket(sockfd);
516516
}
517517
},
518-
function () {
518+
function (sockfd) {
519519
if (errorCB) {
520520
errorCB(
521521
`Could not load ${ssl ? "https" : "http"}://${host}:${port}${path}`
522522
);
523523
}
524+
closeSocket(sockfd)
524525
},
525526
function () {
526527
if (finishCB) {

components/esp32-javascript/modules/esp32-js-eventloop/index.js

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
Object.defineProperty(exports, "__esModule", { value: true });
22
exports.start = exports.afterSuspendHandlers = exports.beforeSuspendHandlers = void 0;
3-
errorhandler =
4-
typeof errorhandler === "undefined"
5-
? function (error) {
6-
console.error("Uncaught error:");
7-
console.error(error.stack || error);
8-
}
9-
: errorhandler;
3+
errorhandler = function () {
4+
// empty default implementation
5+
};
6+
function internalErrorHandler(error) {
7+
console.error("Uncaught error:");
8+
console.error(error.stack || error);
9+
global.el_flushLogBuffer();
10+
errorhandler(error);
11+
}
1012
var timers = [];
1113
var intervals = [];
1214
var handles = 0;
@@ -129,7 +131,7 @@ function start() {
129131
nf();
130132
}
131133
catch (error) {
132-
errorhandler(error);
134+
internalErrorHandler(error);
133135
}
134136
}
135137
});

components/esp32-javascript/modules/esp32-js-eventloop/index.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,18 @@ type Esp32JsEventHandler = (
3333
collected: (() => void)[]
3434
) => boolean;
3535

36-
errorhandler =
37-
typeof errorhandler === "undefined"
38-
? function (error) {
39-
console.error("Uncaught error:");
40-
console.error(error.stack || error);
41-
}
42-
: errorhandler;
36+
errorhandler = function () {
37+
// empty default implementation
38+
};
39+
40+
function internalErrorHandler(error: Error) {
41+
console.error("Uncaught error:");
42+
console.error(error.stack || error);
43+
44+
global.el_flushLogBuffer();
45+
46+
errorhandler(error);
47+
}
4348

4449
const timers: Esp32JsTimer[] = [];
4550
const intervals: number[] = [];
@@ -175,7 +180,7 @@ export function start(): void {
175180
try {
176181
nf();
177182
} catch (error) {
178-
errorhandler(error);
183+
internalErrorHandler(error);
179184
}
180185
}
181186
});

components/socket-events/modules/socket-events/index.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,7 @@ function closeSocket(socketOrSockfd) {
352352
}
353353
performOnClose(socket);
354354
resetSocket(socket);
355+
socket.sockfd = -1;
355356
}
356357
exports.closeSocket = closeSocket;
357358
/**
@@ -369,7 +370,13 @@ exports.closeSocket = closeSocket;
369370
*/
370371
function sockConnect(ssl, host, port, onConnect, onData, onError, onClose) {
371372
var sockfd = el_createNonBlockingSocket();
372-
el_connectNonBlocking(sockfd, host, parseInt(port, 10));
373+
var connectError;
374+
try {
375+
el_connectNonBlocking(sockfd, host, parseInt(port, 10));
376+
}
377+
catch (error) {
378+
connectError = error;
379+
}
373380
var socket = getOrCreateNewSocket();
374381
socket.sockfd = sockfd;
375382
socket.onData = onData;
@@ -403,6 +410,11 @@ function sockConnect(ssl, host, port, onConnect, onData, onError, onClose) {
403410
};
404411
}
405412
exports.sockets.add(socket);
413+
//if connect error occured call the callback
414+
if (connectError && socket.onError) {
415+
console.debug("Error connecting " + host + ":" + port + " : " + connectError);
416+
socket.onError(sockfd);
417+
}
406418
return socket;
407419
}
408420
exports.sockConnect = sockConnect;

components/socket-events/modules/socket-events/index.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,7 @@ export function closeSocket(socketOrSockfd: Esp32JsSocket | number): void {
423423
}
424424
performOnClose(socket);
425425
resetSocket(socket);
426+
socket.sockfd = -1;
426427
}
427428

428429
/**
@@ -448,7 +449,13 @@ export function sockConnect(
448449
onClose: () => void
449450
): Esp32JsSocket {
450451
const sockfd = el_createNonBlockingSocket();
451-
el_connectNonBlocking(sockfd, host, parseInt(port, 10));
452+
453+
let connectError;
454+
try {
455+
el_connectNonBlocking(sockfd, host, parseInt(port, 10));
456+
} catch (error) {
457+
connectError = error;
458+
}
452459

453460
const socket = getOrCreateNewSocket();
454461
socket.sockfd = sockfd;
@@ -483,6 +490,13 @@ export function sockConnect(
483490
}
484491

485492
sockets.add(socket);
493+
494+
//if connect error occured call the callback
495+
if (connectError && socket.onError) {
496+
console.debug(`Error connecting ${host}:${port} : ${connectError}`);
497+
socket.onError(sockfd);
498+
}
499+
486500
return socket;
487501
}
488502

components/socket-events/socket-events.c

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ extern const uint8_t cacert_pem_end[] asm("_binary_cacert_pem_end");
7171
extern const uint8_t prvtkey_pem_start[] asm("_binary_prvtkey_pem_start");
7272
extern const uint8_t prvtkey_pem_end[] asm("_binary_prvtkey_pem_end");
7373

74+
static const char *tag = "esp32-javascript";
75+
7476
int createSocketPair()
7577
{
7678
struct sockaddr_in server;
@@ -321,6 +323,25 @@ void select_task_it()
321323
needsUnblock = false;
322324
}
323325

326+
static void triggerNextSelectIteration()
327+
{
328+
jslog(DEBUG, "Trying to trigger the next select iteration...");
329+
if (selectClientSocket >= 0)
330+
{
331+
//interrupt select through self-socket
332+
jslog(DEBUG, "Sending . to self-socket.");
333+
needsUnblock = true;
334+
if (sendto(selectClientSocket, ".", 1, 0, (struct sockaddr *)&target, sizeof(target)) < 0)
335+
{
336+
jslog(ERROR, "Self-socket sending was NOT successful: %d", errno);
337+
}
338+
else
339+
{
340+
jslog(DEBUG, "Self-socket sending was successful.");
341+
}
342+
}
343+
}
344+
324345
static duk_ret_t el_registerSocketEvents(duk_context *ctx)
325346
{
326347
int c_len, nc_len, cw_len;
@@ -446,21 +467,7 @@ static duk_ret_t el_registerSocketEvents(duk_context *ctx)
446467

447468
if (changes)
448469
{
449-
jslog(DEBUG, "Trying to trigger the next select iteration...");
450-
if (selectClientSocket >= 0)
451-
{
452-
//interrupt select through self-socket
453-
jslog(DEBUG, "Sending . to self-socket.");
454-
needsUnblock = true;
455-
if (sendto(selectClientSocket, ".", 1, 0, (struct sockaddr *)&target, sizeof(target)) < 0)
456-
{
457-
jslog(ERROR, "Self-socket sending was NOT successful: %d", errno);
458-
}
459-
else
460-
{
461-
jslog(DEBUG, "Self-socket sending was successful.");
462-
}
463-
}
470+
triggerNextSelectIteration();
464471
}
465472

466473
//trigger next select loop
@@ -600,6 +607,11 @@ static duk_ret_t connectSSL(duk_context *ctx)
600607
static duk_ret_t el_closeSocket(duk_context *ctx)
601608
{
602609
int socketfd = duk_to_int(ctx, 0);
610+
611+
// prevent bad file descripter error on running select, caused
612+
// by closing socket
613+
triggerNextSelectIteration();
614+
603615
closeSocket(socketfd);
604616
return 0;
605617
}

0 commit comments

Comments
 (0)