diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db5bce89..b07f5e616 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,6 +89,7 @@ Bugfixes: * Fixed building on FreeBSD 16.0-CURRENT, where `` defines `memrchr` as a qualifier-preserving function-like macro. (General, FreeBSD) * Worked around an iTerm bug where the image logo may be moved out of view. (Logo) * Increased the terminal response wait time to 1s to improve compatibility with slower terminals. (General) +* Fixed the `PublicIp` and `Weather` modules exiting with "can only be used once due to internal limitations" on the round after a failed request when `--dynamic-interval` is used, instead of retrying. (PublicIp / Weather) * Some internal cleanups and optimizations. Logos: diff --git a/src/common/networking.h b/src/common/networking.h index 719147214..c5c0e1626 100644 --- a/src/common/networking.h +++ b/src/common/networking.h @@ -34,6 +34,15 @@ typedef struct FFNetworkingState { [[gnu::nonnull(1, 2, 4), nodiscard]] const char* ffNetworkingSendHttpRequest(FFNetworkingState* state, const char* host, uint16_t port, const char* path, const char* headers); [[gnu::nonnull(1, 2), nodiscard]] const char* ffNetworkingRecvHttpResponse(FFNetworkingState* state, FFstrbuf* buffer); +// Releases what a finished request holds and returns `state` to the idle state, so that the next +// `ffNetworkingSendHttpRequest` starts from scratch. A request that never reached the wire can +// still own the request buffer, so a plain zeroing of the struct is not enough. +// The caller stays responsible for its own bookkeeping, such as clearing a "request sent" latch. +[[gnu::nonnull(1)]] static inline void ffNetworkingResetState(FFNetworkingState* state) { + ffStrbufDestroy(&state->command); + *state = (FFNetworkingState) {}; +} + // Case-insensitive header lookup restricted to the header block [0, headerEnd). // Restricting the range matters because the body may already share the same buffer. // Returns a pointer to the first character of the value; `valueLen` receives its diff --git a/src/detection/publicip/publicip.c b/src/detection/publicip/publicip.c index 90efa12d2..cd850efdc 100644 --- a/src/detection/publicip/publicip.c +++ b/src/detection/publicip/publicip.c @@ -103,13 +103,16 @@ const char* ffDetectPublicIp(FFPublicIPOptions* options, FFPublicIpResult* resul } if (*status != nullptr) { - return *status; + const char* error = *status; + ffNetworkingResetState(state); + *status = FF_UNINITIALIZED; + return error; } FF_STRBUF_AUTO_DESTROY response = ffStrbufCreateA(4096); const char* error = ffNetworkingRecvHttpResponse(state, &response); - *state = (FFNetworkingState) {}; + ffNetworkingResetState(state); *status = FF_UNINITIALIZED; if (error == nullptr) { diff --git a/src/detection/weather/weather.c b/src/detection/weather/weather.c index 2899456f1..b258d8f2c 100644 --- a/src/detection/weather/weather.c +++ b/src/detection/weather/weather.c @@ -38,13 +38,16 @@ const char* ffDetectWeather(FFWeatherOptions* options, FFstrbuf* result) { } if (status != nullptr) { - return status; + const char* error = status; + ffNetworkingResetState(&state); + status = FF_UNITIALIZED; + return error; } ffStrbufEnsureFree(result, 4095); const char* error = ffNetworkingRecvHttpResponse(&state, result); - state = (FFNetworkingState) {}; + ffNetworkingResetState(&state); status = FF_UNITIALIZED; if (error == nullptr) { diff --git a/src/fastfetch.c b/src/fastfetch.c index a5c3ec20f..980bf7c06 100644 --- a/src/fastfetch.c +++ b/src/fastfetch.c @@ -690,7 +690,7 @@ static void parseCommand(FFdata* data, char* key, char* value) { enableJsonOutput(data); } } else if (ffStrEqualsIgnCase(key, "--dynamic-interval")) { - instance.state.dynamicInterval = ffOptionParseUInt32(key, value); // seconds to milliseconds + instance.state.dynamicInterval = ffOptionParseUInt32(key, value); // ms } else if (ffStrEqualsIgnCase(key, "-w") || ffStrEqualsIgnCase(key, "--watch")) { if (value == nullptr) { instance.state.dynamicInterval = 1000; // default to 1 second if no value is provided