mirror of https://github.com/jetkvm/kvm.git
fix git merge conflict
This commit is contained in:
parent
75ea98d396
commit
736bf0af04
|
|
@ -1,210 +0,0 @@
|
|||
diff --git a/internal/native/cgo/video.c b/internal/native/cgo/video.c
|
||||
index 2a4a034..760621a 100644
|
||||
--- a/internal/native/cgo/video.c
|
||||
+++ b/internal/native/cgo/video.c
|
||||
@@ -354,6 +354,10 @@ bool detected_signal = false, streaming_flag = false, streaming_stopped = true;
|
||||
pthread_t *streaming_thread = NULL;
|
||||
pthread_mutex_t streaming_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
+// Diagnostic tracking for validation
|
||||
+static uint64_t last_close_time = 0;
|
||||
+static int consecutive_failures = 0;
|
||||
+
|
||||
bool get_streaming_flag()
|
||||
{
|
||||
log_info("getting streaming flag");
|
||||
@@ -395,6 +399,12 @@ void *run_video_stream(void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
+ // Log attempt to open with timing info
|
||||
+ RK_U64 time_since_close = last_close_time > 0 ? (get_us() - last_close_time) : 0;
|
||||
+ log_info("[DIAG] Attempting to open %s (time_since_last_close=%llu us)",
|
||||
+ VIDEO_DEV, time_since_close);
|
||||
+
|
||||
+ RK_U64 open_start_time = get_us();
|
||||
int video_dev_fd = open(VIDEO_DEV, O_RDWR);
|
||||
if (video_dev_fd < 0)
|
||||
{
|
||||
@@ -402,7 +412,9 @@ void *run_video_stream(void *arg)
|
||||
usleep(1000000);
|
||||
continue;
|
||||
}
|
||||
- log_info("opened video capture device %s", VIDEO_DEV);
|
||||
+ RK_U64 open_end_time = get_us();
|
||||
+ log_info("[DIAG] opened video capture device %s in %llu us",
|
||||
+ VIDEO_DEV, open_end_time - open_start_time);
|
||||
|
||||
uint32_t width = detected_width;
|
||||
uint32_t height = detected_height;
|
||||
@@ -414,14 +426,45 @@ void *run_video_stream(void *arg)
|
||||
fmt.fmt.pix_mp.pixelformat = V4L2_PIX_FMT_YUYV;
|
||||
fmt.fmt.pix_mp.field = V4L2_FIELD_ANY;
|
||||
|
||||
+ // Probe device state before attempting format set
|
||||
+ struct v4l2_format query_fmt;
|
||||
+ memset(&query_fmt, 0, sizeof(query_fmt));
|
||||
+ query_fmt.type = type;
|
||||
+ int query_ret = ioctl(video_dev_fd, VIDIOC_G_FMT, &query_fmt);
|
||||
+ log_info("[DIAG] VIDIOC_G_FMT probe: ret=%d, errno=%d (%s)",
|
||||
+ query_ret, query_ret < 0 ? errno : 0,
|
||||
+ query_ret < 0 ? strerror(errno) : "OK");
|
||||
+
|
||||
+ RK_U64 set_fmt_start_time = get_us();
|
||||
+ log_info("[DIAG] Attempting VIDIOC_S_FMT: %ux%u, time_since_open=%llu us",
|
||||
+ width, height, set_fmt_start_time - open_end_time);
|
||||
+
|
||||
if (ioctl(video_dev_fd, VIDIOC_S_FMT, &fmt) < 0)
|
||||
{
|
||||
- log_error("Set format fail: %s", strerror(errno));
|
||||
+ RK_U64 failure_time = get_us();
|
||||
+ int saved_errno = errno;
|
||||
+ consecutive_failures++;
|
||||
+
|
||||
+ log_error("[DIAG] Set format fail: errno=%d (%s)", saved_errno, strerror(saved_errno));
|
||||
+ log_error("[DIAG] Failure context: consecutive_failures=%d, time_since_open=%llu us, "
|
||||
+ "time_since_last_close=%llu us, resolution=%ux%u, streaming_flag=%d",
|
||||
+ consecutive_failures,
|
||||
+ failure_time - open_end_time,
|
||||
+ last_close_time > 0 ? (open_start_time - last_close_time) : 0,
|
||||
+ width, height,
|
||||
+ streaming_flag);
|
||||
+
|
||||
usleep(100000); // Sleep for 100 milliseconds
|
||||
close(video_dev_fd);
|
||||
+ last_close_time = get_us();
|
||||
+ log_info("[DIAG] Closed device after format failure at %llu us", last_close_time);
|
||||
continue;
|
||||
}
|
||||
|
||||
+ // Success - reset failure counter
|
||||
+ log_info("[DIAG] VIDIOC_S_FMT succeeded (previous consecutive failures: %d)", consecutive_failures);
|
||||
+ consecutive_failures = 0;
|
||||
+
|
||||
struct v4l2_buffer buf;
|
||||
|
||||
struct v4l2_requestbuffers req;
|
||||
@@ -601,9 +644,46 @@ void *run_video_stream(void *arg)
|
||||
}
|
||||
cleanup:
|
||||
log_info("cleaning up video capture device %s", VIDEO_DEV);
|
||||
- if (ioctl(video_dev_fd, VIDIOC_STREAMOFF, &type) < 0)
|
||||
+
|
||||
+ RK_U64 streamoff_start = get_us();
|
||||
+ log_info("[DIAG] Attempting VIDIOC_STREAMOFF");
|
||||
+
|
||||
+ int streamoff_ret = ioctl(video_dev_fd, VIDIOC_STREAMOFF, &type);
|
||||
+ RK_U64 streamoff_end = get_us();
|
||||
+
|
||||
+ if (streamoff_ret < 0)
|
||||
+ {
|
||||
+ log_error("[DIAG] VIDIOC_STREAMOFF failed: errno=%d (%s), duration=%llu us",
|
||||
+ errno, strerror(errno), streamoff_end - streamoff_start);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ log_info("[DIAG] VIDIOC_STREAMOFF succeeded in %llu us",
|
||||
+ streamoff_end - streamoff_start);
|
||||
+ }
|
||||
+
|
||||
+ // VALIDATION TEST: Explicitly free V4L2 buffer queue
|
||||
+ struct v4l2_requestbuffers req_free;
|
||||
+ memset(&req_free, 0, sizeof(req_free));
|
||||
+ req_free.count = 0; // Tell driver to free all buffers
|
||||
+ req_free.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
|
||||
+ req_free.memory = V4L2_MEMORY_DMABUF;
|
||||
+
|
||||
+ RK_U64 reqbufs_start = get_us();
|
||||
+ log_info("[DIAG] VALIDATION: Calling VIDIOC_REQBUFS(count=0) to free buffer queue");
|
||||
+
|
||||
+ int reqbufs_ret = ioctl(video_dev_fd, VIDIOC_REQBUFS, &req_free);
|
||||
+ RK_U64 reqbufs_end = get_us();
|
||||
+
|
||||
+ if (reqbufs_ret < 0)
|
||||
+ {
|
||||
+ log_error("[DIAG] VALIDATION: REQBUFS(0) FAILED - errno=%d (%s), duration=%llu us",
|
||||
+ errno, strerror(errno), reqbufs_end - reqbufs_start);
|
||||
+ }
|
||||
+ else
|
||||
{
|
||||
- log_error("VIDIOC_STREAMOFF failed: %s", strerror(errno));
|
||||
+ log_info("[DIAG] VALIDATION: REQBUFS(0) SUCCEEDED - freed buffers in %llu us",
|
||||
+ reqbufs_end - reqbufs_start);
|
||||
}
|
||||
|
||||
venc_stop();
|
||||
@@ -617,9 +697,13 @@ void *run_video_stream(void *arg)
|
||||
}
|
||||
|
||||
log_info("closing video capture device %s", VIDEO_DEV);
|
||||
+ RK_U64 close_start = get_us();
|
||||
close(video_dev_fd);
|
||||
+ last_close_time = get_us();
|
||||
+ log_info("[DIAG] Device closed, took %llu us, timestamp=%llu",
|
||||
+ last_close_time - close_start, last_close_time);
|
||||
}
|
||||
-
|
||||
+
|
||||
log_info("video stream thread exiting");
|
||||
|
||||
streaming_stopped = true;
|
||||
@@ -648,7 +732,7 @@ void video_shutdown()
|
||||
RK_MPI_MB_DestroyPool(memPool);
|
||||
}
|
||||
log_info("Destroyed memory pool");
|
||||
-
|
||||
+
|
||||
pthread_mutex_destroy(&streaming_mutex);
|
||||
log_info("Destroyed streaming mutex");
|
||||
}
|
||||
@@ -665,14 +749,14 @@ void video_start_streaming()
|
||||
log_warn("video streaming already started");
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
pthread_t *new_thread = malloc(sizeof(pthread_t));
|
||||
if (new_thread == NULL)
|
||||
{
|
||||
log_error("Failed to allocate memory for streaming thread");
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
set_streaming_flag(true);
|
||||
int result = pthread_create(new_thread, NULL, run_video_stream, NULL);
|
||||
if (result != 0)
|
||||
@@ -682,7 +766,7 @@ void video_start_streaming()
|
||||
free(new_thread);
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
// Only set streaming_thread after successful creation
|
||||
streaming_thread = new_thread;
|
||||
}
|
||||
@@ -693,7 +777,7 @@ void video_stop_streaming()
|
||||
log_info("video streaming already stopped");
|
||||
return;
|
||||
}
|
||||
-
|
||||
+
|
||||
log_info("stopping video streaming");
|
||||
set_streaming_flag(false);
|
||||
|
||||
@@ -711,7 +795,7 @@ void video_stop_streaming()
|
||||
free(streaming_thread);
|
||||
streaming_thread = NULL;
|
||||
|
||||
- log_info("video streaming stopped");
|
||||
+ log_info("video streaming stopped");
|
||||
}
|
||||
|
||||
void video_restart_streaming()
|
||||
@@ -818,4 +902,4 @@ void video_set_quality_factor(float factor)
|
||||
|
||||
float video_get_quality_factor() {
|
||||
return quality_factor;
|
||||
-}
|
||||
\ No newline at end of file
|
||||
+}
|
||||
76
network.go
76
network.go
|
|
@ -2,10 +2,8 @@ package kvm
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
"github.com/jetkvm/kvm/internal/network"
|
||||
"github.com/jetkvm/kvm/internal/ota"
|
||||
"github.com/jetkvm/kvm/internal/udhcpc"
|
||||
)
|
||||
|
||||
|
|
@ -84,79 +82,21 @@ func initNetwork() error {
|
|||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func setHostname(nm *nmlite.NetworkManager, hostname, domain string) error {
|
||||
if nm == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if hostname == "" {
|
||||
hostname = GetDefaultHostname()
|
||||
}
|
||||
|
||||
return nm.SetHostname(hostname, domain)
|
||||
}
|
||||
|
||||
func shouldRebootForNetworkChange(oldConfig, newConfig *types.NetworkConfig) (rebootRequired bool, postRebootAction *ota.PostRebootAction) {
|
||||
oldDhcpClient := oldConfig.DHCPClient.String
|
||||
|
||||
l := networkLogger.With().
|
||||
Interface("old", oldConfig).
|
||||
Interface("new", newConfig).
|
||||
Logger()
|
||||
|
||||
// DHCP client change always requires reboot
|
||||
if newConfig.DHCPClient.String != oldDhcpClient {
|
||||
rebootRequired = true
|
||||
l.Info().Msg("DHCP client changed, reboot required")
|
||||
return rebootRequired, postRebootAction
|
||||
}
|
||||
|
||||
oldIPv4Mode := oldConfig.IPv4Mode.String
|
||||
newIPv4Mode := newConfig.IPv4Mode.String
|
||||
|
||||
// IPv4 mode change requires reboot
|
||||
if newIPv4Mode != oldIPv4Mode {
|
||||
rebootRequired = true
|
||||
l.Info().Msg("IPv4 mode changed with udhcpc, reboot required")
|
||||
|
||||
if newIPv4Mode == "static" && oldIPv4Mode != "static" {
|
||||
postRebootAction = &ota.PostRebootAction{
|
||||
HealthCheck: fmt.Sprintf("//%s/device/status", newConfig.IPv4Static.Address.String),
|
||||
RedirectTo: fmt.Sprintf("//%s", newConfig.IPv4Static.Address.String),
|
||||
}
|
||||
l.Info().Interface("postRebootAction", postRebootAction).Msg("IPv4 mode changed to static, reboot required")
|
||||
if state == nil {
|
||||
if err == nil {
|
||||
return fmt.Errorf("failed to create NetworkInterfaceState")
|
||||
}
|
||||
|
||||
return rebootRequired, postRebootAction
|
||||
return err
|
||||
}
|
||||
|
||||
// IPv4 static config changes require reboot
|
||||
if !reflect.DeepEqual(oldConfig.IPv4Static, newConfig.IPv4Static) {
|
||||
rebootRequired = true
|
||||
|
||||
// Handle IP change for redirect (only if both are not nil and IP changed)
|
||||
if newConfig.IPv4Static != nil && oldConfig.IPv4Static != nil &&
|
||||
newConfig.IPv4Static.Address.String != oldConfig.IPv4Static.Address.String {
|
||||
postRebootAction = &ota.PostRebootAction{
|
||||
HealthCheck: fmt.Sprintf("//%s/device/status", newConfig.IPv4Static.Address.String),
|
||||
RedirectTo: fmt.Sprintf("//%s", newConfig.IPv4Static.Address.String),
|
||||
}
|
||||
|
||||
l.Info().Interface("postRebootAction", postRebootAction).Msg("IPv4 static config changed, reboot required")
|
||||
}
|
||||
|
||||
return rebootRequired, postRebootAction
|
||||
if err := state.Run(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// IPv6 mode change requires reboot when using udhcpc
|
||||
if newConfig.IPv6Mode.String != oldConfig.IPv6Mode.String && oldDhcpClient == "udhcpc" {
|
||||
rebootRequired = true
|
||||
l.Info().Msg("IPv6 mode changed with udhcpc, reboot required")
|
||||
}
|
||||
networkState = state
|
||||
|
||||
return rebootRequired, postRebootAction
|
||||
return nil
|
||||
}
|
||||
|
||||
func rpcGetNetworkState() network.RpcNetworkState {
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
#!/bin/bash
|
||||
set -eE
|
||||
set -o pipefail
|
||||
|
||||
SCRIPT_PATH=$(realpath "$(dirname $(realpath "${BASH_SOURCE[0]}"))")
|
||||
source ${SCRIPT_PATH}/build_utils.sh
|
||||
|
||||
# Function to display help message
|
||||
show_help() {
|
||||
echo "Usage: $0 [options] -v <version>"
|
||||
echo
|
||||
echo "Required:"
|
||||
echo " --app-version <version> App version to release"
|
||||
echo " --system-version <version> System version to release"
|
||||
echo
|
||||
echo "Optional:"
|
||||
echo " -u, --user <remote_user> Remote username (default: root)"
|
||||
echo " --run-go-tests Run go tests"
|
||||
echo " --run-go-tests-only Run go tests and exit"
|
||||
echo " --skip-ui-build Skip frontend/UI build"
|
||||
echo " --skip-native-build Skip native build"
|
||||
echo " --disable-docker Disable docker build"
|
||||
echo " -i, --install Build for release and install the app"
|
||||
echo " --help Display this help message"
|
||||
echo
|
||||
echo "Example:"
|
||||
echo " $0 --system-version 0.2.6"
|
||||
}
|
||||
|
||||
|
||||
BUILD_VERSION=$1
|
||||
R2_PATH="r2://jetkvm-update/system"
|
||||
PACK_BIN_PATH="./tools/linux/Linux_Pack_Firmware"
|
||||
UNPACK_BIN="${PACK_BIN_PATH}/mk-update_unpack.sh"
|
||||
|
||||
# Create temporary directory for downloads
|
||||
TEMP_DIR=$(mktemp -d)
|
||||
msg_ok "Created temporary directory: $TEMP_DIR"
|
||||
|
||||
# Cleanup function
|
||||
cleanup() {
|
||||
if [ -d "$TEMP_DIR" ]; then
|
||||
msg_info "Cleaning up temporary directory: $TEMP_DIR"
|
||||
rm -rf "$TEMP_DIR"
|
||||
fi
|
||||
}
|
||||
|
||||
# Set trap to cleanup on exit
|
||||
# trap cleanup EXIT
|
||||
|
||||
mkdir -p ${TEMP_DIR}/extracted-update
|
||||
${UNPACK_BIN} -i update.img -o ${TEMP_DIR}/extracted-update
|
||||
|
||||
exit 0
|
||||
# Check if the version already exists
|
||||
if rclone lsf $R2_PATH/$BUILD_VERSION/ | grep -q .; then
|
||||
msg_err "Error: Version $BUILD_VERSION already exists in the remote storage."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the version exists in the github
|
||||
RELEASE_URL="https://api.github.com/repos/jetkvm/rv1106-system/releases/tags/v$BUILD_VERSION"
|
||||
|
||||
# Download the release JSON
|
||||
RELEASE_JSON=$(curl -s $RELEASE_URL)
|
||||
|
||||
# Check if the release has assets we need
|
||||
if echo $RELEASE_JSON | jq -e '.assets | length == 0' > /dev/null; then
|
||||
msg_err "Error: Version $BUILD_VERSION does not have assets we need."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function get_file_by_name() {
|
||||
local file_name=$1
|
||||
local file_url=$(echo $RELEASE_JSON | jq -r ".assets[] | select(.name == \"$file_name\") | .browser_download_url")
|
||||
if [ -z "$file_url" ]; then
|
||||
msg_err "Error: File $file_name not found in the release."
|
||||
exit 1
|
||||
fi
|
||||
local digest=$(echo $RELEASE_JSON | jq -r ".assets[] | select(.name == \"$file_name\") | .digest")
|
||||
local temp_file_path="$TEMP_DIR/$file_name"
|
||||
|
||||
msg_info "Downloading $file_name: $file_url"
|
||||
|
||||
# Download the file to temporary directory
|
||||
curl -L -o "$temp_file_path" "$file_url"
|
||||
|
||||
# Verify digest if available
|
||||
if [ "$digest" != "null" ] && [ -n "$digest" ]; then
|
||||
msg_info "Verifying digest for $file_name ..."
|
||||
local calculated_digest=$(sha256sum "$temp_file_path" | cut -d' ' -f1)
|
||||
# Strip "sha256:" prefix if present
|
||||
local expected_digest=$(echo "$digest" | sed 's/^sha256://')
|
||||
if [ "$calculated_digest" != "$expected_digest" ]; then
|
||||
msg_err "🙅 Digest verification failed for $file_name"
|
||||
msg_info "Expected: $expected_digest"
|
||||
msg_info "Calculated: $calculated_digest"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
msg_warn "Warning: No digest available for $file_name, skipping verification"
|
||||
fi
|
||||
|
||||
msg_ok "✅ $file_name downloaded and verified."
|
||||
}
|
||||
|
||||
get_file_by_name "update_ota.tar"
|
||||
get_file_by_name "update.img"
|
||||
|
||||
strings -d bin/jetkvm_app | grep -x '0.4.8'
|
||||
|
||||
# Ask for confirmation
|
||||
msg_info "Do you want to continue with the release? (y/n)"
|
||||
read -n 1 -s -r -p "Press y to continue, any other key to exit"
|
||||
echo -ne "\n"
|
||||
if [ "$REPLY" != "y" ]; then
|
||||
msg_err "🙅 Release cancelled."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
msg_info "Releasing $BUILD_VERSION..."
|
||||
|
||||
sha256sum $TEMP_DIR/update_ota.tar | awk '{print $1}' > $TEMP_DIR/update_ota.tar.sha256
|
||||
sha256sum $TEMP_DIR/update.img | awk '{print $1}' > $TEMP_DIR/update.img.sha256
|
||||
|
||||
# Check if the version already exists
|
||||
msg_info "Copying to $R2_PATH/$BUILD_VERSION/"
|
||||
|
||||
rclone copyto --progress $TEMP_DIR/update_ota.tar $R2_PATH/$BUILD_VERSION/system.tar
|
||||
rclone copyto --progress $TEMP_DIR/update_ota.tar.sha256 $R2_PATH/$BUILD_VERSION/system.tar.sha256
|
||||
rclone copyto --progress $TEMP_DIR/update.img $R2_PATH/$BUILD_VERSION/update.img
|
||||
rclone copyto --progress $TEMP_DIR/update.img.sha256 $R2_PATH/$BUILD_VERSION/update.img.sha256
|
||||
|
||||
msg_ok "✅ $BUILD_VERSION released."
|
||||
Loading…
Reference in New Issue