WPS function "wiced_wps_enrollee" makes an endless loop and the process does not end

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
KEKA_4568351
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

I have a WiFi connection by WPS, and I have acquired the SSID and password with the WPS function "wiced_wps_enrollee", but when I repeat the WiFi connection ⇒ disconnection, the WPS function "wiced_wps_enrollee" becomes a permanent loop state and the process does not end The phenomenon is occurring.

# Repeat 10 times and it will stop once.

For a rough processing procedure, see "◆ Processing".

When I log the wiced_wps_enrollee function and execute it, "wiced_wps_enrollee - 03" causes an endless loop, and the part of the endless loop becomes a while loop of the "wwd_rtos.c" - "host_rtos_join_thread" function.

For confirmation by running the debugger, see the image file "snap-01.png".

I have two questions.

◆ QA

1. wiced_wps_thread_main(\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\security\BESL\host\WICED\wiced_wps.c)

   I think that it is waiting for the processing of the wps_enrollee_start function. Is there a way to end the processing?

   ▼wiced_wps_thread_main function code

    WPS_INFO(("Starting WPS Enrollee\n"));

    wps_enrollee_start( workspace, workspace->interface );

2. I would like to safely end the part of the endless loop, I'm considering the additional code below, is that okay?

   If you have any problems, please comment.

▼ Code under consideration

wwd_result_t host_rtos_join_thread( host_thread_type_t* thread )

{

    int cnt = 0;    // ★additional code

    if (thread == NULL || thread->tx_thread_id != TX_THREAD_ID)

    {

        /*

         * Invalid thread pointer.

         */

        return WWD_BADARG;

    }

    while ( ( thread->tx_thread_state != TX_COMPLETED ) && ( thread->tx_thread_state != TX_TERMINATED ) )

    {

        host_rtos_delay_milliseconds( 10 );

        cnt++;                   // ★additional code.

        if(12000 <= cnt) {  // ★additional code. ※End after 120 seconds

            break;              // ★additional code.

        }                          // ★additional code.

    }

    return WWD_SUCCESS;

}

◆ Processing

1. wiced_wps_enrollee: Get information

2. wifi_utils_join: Wifi connection

3. Execute SNTP time acquisition, MQTT connection, MQTT subscribe, MQTT publish, etc.

4. wwd_wifi_is_ready_to_transceive & wiced_network_down: Network disconnection

◆Log

[2020-04-23 16:12:25.211] [WIF_INF] wiced_wps_enrollee start. ... XXX(XXX)

[2020-04-23 16:12:29.224] wiced_wps_enrollee - 01

[2020-04-23 16:12:29.224] wiced_wps_enrollee - 02

[2020-04-23 16:12:29.977] wiced_wps_enrollee - 03 ★03 is a permanent loop state

◆Code with log for wiced_wps_enrollee function(\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\internal\wifi.c)

wiced_result_t wiced_wps_enrollee(wiced_wps_mode_t mode, const wiced_wps_device_detail_t* details, const char* password, wiced_wps_credential_t* credentials, uint16_t credential_count)

{

    wiced_result_t result    = WICED_SUCCESS;

    wps_agent_t*   workspace = (wps_agent_t*) calloc_named("wps", 1, sizeof(wps_agent_t));

    if ( workspace == NULL )

    {

        return WICED_OUT_OF_HEAP_SPACE;

    }

WPRINT_APP_INFO(("wiced_wps_enrollee - 01 \n"));

besl_wps_init ( workspace, (besl_wps_device_detail_t*) details, WPS_ENROLLEE_AGENT, WWD_STA_INTERFACE );

WPRINT_APP_INFO(("wiced_wps_enrollee - 02 \n"));

    result = (wiced_result_t) besl_wps_start( workspace, (besl_wps_mode_t) mode, password, (besl_wps_credential_t*) credentials, credential_count );

    host_rtos_delay_milliseconds( 10 ); /* Delay required to allow WPS thread to run and initialize */

    if ( result == WICED_SUCCESS )

    {

WPRINT_APP_INFO(("wiced_wps_enrollee - 03 \n"));

        besl_wps_wait_till_complete( workspace );

        result = (wiced_result_t) besl_wps_get_result( workspace );

    }

WPRINT_APP_INFO(("wiced_wps_enrollee - 04 \n"));

    besl_wps_deinit( workspace );

    free( workspace );

    workspace = NULL;

    return result;

}

◆Code for an endless loop(\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\RTOS\ThreadX\WWD\wwd_rtos.c)

/**

* Blocks the current thread until the indicated thread is complete

*

* @param thread         : handle of the thread to terminate

*

* @returns WWD_SUCCESS on success, WICED_ERROR otherwise

*/

wwd_result_t host_rtos_join_thread( host_thread_type_t* thread )

{

    if (thread == NULL || thread->tx_thread_id != TX_THREAD_ID)

    {

        /*

         * Invalid thread pointer.

         */

        return WWD_BADARG;

    }

    while ( ( thread->tx_thread_state != TX_COMPLETED ) && ( thread->tx_thread_state != TX_TERMINATED ) )  ★This loop puts you in a waiting state forever

    {

        host_rtos_delay_milliseconds( 10 );

    }

    return WWD_SUCCESS;

}

0 Likes
1 Solution

Thanks for the details. There is some latency involved between calling wiced_aws_disconnect() which pushes the disconnect event to the RTOS queue with no wait and finally getting the WICED_AWS_EVENT_DISCONNECTED event. With the setting of no wait, it is not a blocking function. Which meaans that during this latency period, if wiced_wps_enrollee() is being called, it will call host_rtos_join_thread() which blocks the current thread until the thread specified in the function completes. This would have caused a deadlock. Adding the 5 second delay would have given sufficient time for wiced_aws_disconnect() to complete its operation. But instead of delay, you can also try using semaphore to ensure that the disconnect event is received. You can call wiced_rtos_get_semaphore() after wiced_aws_disconnect() and under case WICED_AWS_EVENT_DISCONNECTED, you can call wiced_rtos_set_semaphore(). This should avoid any potential deadlock issues.

View solution in original post

12 Replies
KEKA_4568351
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

<Japanese>

WPS関数「wiced_wps_enrollee」で、永久ループになり、処理が終了しない

WPSによる、WiFi接続を行っており、WPS関数「wiced_wps_enrollee」により、SSID、パスワードを取得していますが、WiFi接続⇒切断を繰り返すと、WPS関数「wiced_wps_enrollee」が永久ループ状態となり、処理が終了しない現象が発生しています。

#10回繰り返すと、1回停止する頻度です。

大まかな、処理手順は、「◆処理」を参照してください。

wiced_wps_enrollee関数にログをつけて実行したところ、「wiced_wps_enrollee - 03」で、永久ループ状態となり、永久ループの箇所は、「wwd_rtos.c」-「host_rtos_join_thread」関数のwhileループになります。

デバッガ実行による確認は、画像ファイル「snap-01.png」をご覧ください。

2点質問があります。

◆QA

1.wiced_wps_thread_main(\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\security\BESL\host\WICED\wiced_wps.c)のwps_enrollee_start関数の処理待ちだと思いますが、処理を終了する方法はありますか。

    ▼wiced_wps_thread_main関数コード

    WPS_INFO(("Starting WPS Enrollee\n"));

    wps_enrollee_start( workspace, workspace->interface );

2.永久ループの箇所を安全に終了させたいと思いますが、以下の追加コードを検討していますが、良いでしょうか。

    問題があれば、コメントをください。

▼検討中のコード

wwd_result_t host_rtos_join_thread( host_thread_type_t* thread )

{

    int cnt = 0;    // ★additional code

    if (thread == NULL || thread->tx_thread_id != TX_THREAD_ID)

    {

        /*

         * Invalid thread pointer.

         */

        return WWD_BADARG;

    }

    while ( ( thread->tx_thread_state != TX_COMPLETED ) && ( thread->tx_thread_state != TX_TERMINATED ) )

    {

        host_rtos_delay_milliseconds( 10 );

        cnt++;                    // ★additional code.

        if(12000 <= cnt) {   // ★additional code. ※120秒経過したら終了

            break;                // ★additional code.

        }                            // ★additional code.

    }

    return WWD_SUCCESS;

}

◆処理

1.wiced_wps_enrollee:情報を取得

2.wifi_utils_join:Wifi接続

3.SNTP時刻取得、MQTT接続、MQTTサブスクライブ、MQTTパブリッシュ 等を実行

4.wwd_wifi_is_ready_to_transceive&wiced_network_down:ネットワーク切断

◆ログ

[2020-04-23 16:12:25.211] [WIF_INF] wiced_wps_enrollee start. ... XXX(XXX)

[2020-04-23 16:12:29.224] wiced_wps_enrollee - 01

[2020-04-23 16:12:29.224] wiced_wps_enrollee - 02

[2020-04-23 16:12:29.977] wiced_wps_enrollee - 03 ★03で永久ループ状態

◆wiced_wps_enrollee関数のログを付けたコード(\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\internal\wifi.c)

wiced_result_t wiced_wps_enrollee(wiced_wps_mode_t mode, const wiced_wps_device_detail_t* details, const char* password, wiced_wps_credential_t* credentials, uint16_t credential_count)

{

    wiced_result_t result    = WICED_SUCCESS;

    wps_agent_t*   workspace = (wps_agent_t*) calloc_named("wps", 1, sizeof(wps_agent_t));

    if ( workspace == NULL )

    {

        return WICED_OUT_OF_HEAP_SPACE;

    }

WPRINT_APP_INFO(("wiced_wps_enrollee - 01 \n"));

besl_wps_init ( workspace, (besl_wps_device_detail_t*) details, WPS_ENROLLEE_AGENT, WWD_STA_INTERFACE );

WPRINT_APP_INFO(("wiced_wps_enrollee - 02 \n"));

    result = (wiced_result_t) besl_wps_start( workspace, (besl_wps_mode_t) mode, password, (besl_wps_credential_t*) credentials, credential_count );

    host_rtos_delay_milliseconds( 10 ); /* Delay required to allow WPS thread to run and initialize */

    if ( result == WICED_SUCCESS )

    {

WPRINT_APP_INFO(("wiced_wps_enrollee - 03 \n"));

        besl_wps_wait_till_complete( workspace );

        result = (wiced_result_t) besl_wps_get_result( workspace );

    }

WPRINT_APP_INFO(("wiced_wps_enrollee - 04 \n"));

    besl_wps_deinit( workspace );

    free( workspace );

    workspace = NULL;

    return result;

}

◆永久ループのコード(\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\RTOS\ThreadX\WWD\wwd_rtos.c)

/**

* Blocks the current thread until the indicated thread is complete

*

* @param thread         : handle of the thread to terminate

*

* @returns WWD_SUCCESS on success, WICED_ERROR otherwise

*/

wwd_result_t host_rtos_join_thread( host_thread_type_t* thread )

{

    if (thread == NULL || thread->tx_thread_id != TX_THREAD_ID)

    {

        /*

         * Invalid thread pointer.

         */

        return WWD_BADARG;

    }

    while ( ( thread->tx_thread_state != TX_COMPLETED ) && ( thread->tx_thread_state != TX_TERMINATED ) )  ★このループで、永久に待ち状態となる

    {

        host_rtos_delay_milliseconds( 10 );

    }

    return WWD_SUCCESS;

}

0 Likes

1. The program execution should exit the host_rtos_join_thread() loop at the end of WPS timeout which is 2 minutes by default. Are you saying that the execution continues to remain stuck even after 2 minutes?

2. Modifying the host_rtos_join_thread() is generally not recommended because the same function is used by different applications and threads and there might be a possibility that for certain threads, it may take longer than 120 seconds to execute the function. In other words, if you want to modify, you will need to ensure that your other applications and threads are not impacted due to this modification.

1. Even after 10 minutes or more, the endless loop continues.

2. understood. Do not modify the host_rtos_join_thread function. Is there another plan?

<Japanese>

1.10分以上経過しても、永久ループが続きます。

2.わかりました。host_rtos_join_thread関数の修正はやめます。別の案はありますか。

0 Likes

◆ Addition

2. With the host_rtos_join_thread function, add a flag, turn on the flag only for the problem processing, and try to respond.

◆追加

<Japanese>

2.host_rtos_join_thread関数で、フラグを追加して、問題の処理のみフラグをONにして、対応してみます。

0 Likes

When the following header files were changed and operated, the logs "WPS join failed on interface 0" and "WPS scan failure" were displayed.

◆ Question

I think that it is the process inside the "wps_enrollee_start" function, but if you know the possible cause, please let me know.

◆ \ WICED-Studio-6.4 \ 43xxx_Wi-Fi \ include \ wiced_defaults.h

#define WPRINT_ENABLE_WPS_INFO / * WPS stack prints * /

#define WPRINT_ENABLE_WPS_DEBUG

#define WPRINT_ENABLE_WPS_ERROR

◆ Log

wiced_wps_enrollee-01

wiced_wps_enrollee-02

Starting WPS Enrollee

wiced_wps_enrollee-03

Joining 'Buffalo-G-35E8'

WPS join failed on interface 0

WPS scan failure

WPS scan failure

WPS scan failure

<Japanese>

以下のヘッダファイルを変更して、動作させたところ、「WPS join failed on interface 0」、「WPS scan failure」のログが表示されました。

◆質問

「wps_enrollee_start」関数内の処理だと思いますが、考えられる原因がわかりましたら、教えてください。

0 Likes

I tried fixing the "host_rtos_join_thread" function, but it hangs in the besl_wps_deinit function in "wiced_wps_enrollee-04". (Permanent loop)

The proposed amendment was NG.

I have to consider another plan.

<Japanese>

「host_rtos_join_thread」関数の修正試しましたが、「wiced_wps_enrollee - 04」のbesl_wps_deinit関数内で停止します。(永久ループ)

修正の案としては、NGでした。

別の案を検討しないといけません。

0 Likes

It was NG, but I will attach the source.

<Japanese>

NGでしたが、ソースを添付いたします。

0 Likes

◆wifi.c

\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\internal\

◆wwd_rtos.c

\WICED-Studio-6.4\43xxx_Wi-Fi\WICED\RTOS\ThreadX\WWD\

0 Likes

After making the following corrections, it seems that the problem has been resolved.

The fix is to add a delay of 5 seconds after the "wiced_aws_disconnect" function of the MQTT disconnect process before the wiced_wps_enrollee function. (Refer to the code)

As a result, the phenomenon that the wiced_wps_enrollee function becomes an endless loop disappeared, but I have a question because the relationship is unknown.

◆ QA

I added a delay of 5 seconds after the "wiced_aws_disconnect" function to wait for the WICED_MQTT_EVENT_TYPE_DISCONNECTED event. Is the MQTT event affecting the processing of the wiced_wps_enrollee function?

Please let me know if there are any possible causes.

◆ Code

static void WiFi_wifi_connect_auto_thread( void )

{

    ・・・・

    /* ★MQTT disconnect★ */

    WiFi_mqtt_disconnect();

    wwd_result = wwd_wifi_is_ready_to_transceive(WICED_STA_INTERFACE);

    if(WWD_SUCCESS == wwd_result) {

        wiced_network_down(WICED_STA_INTERFACE);

    }

    /* ★wiced_wps_enrollee★ */

    wiced_result = wiced_wps_enrollee(WICED_WPS_PBC_MODE, &wps_details, "00000000", &wps_credentials, 1);

    ・・・

}

/* ★MQTT disconnect★ */

apps_result_t WiFi_mqtt_disconnect( void )

{

    apps_result_t       ret = APPS_SUCCESS;

    wiced_result_t      wiced_result;

    wiced_aws_internal_handle_t*    p_aws = NULL;

    wiced_mqtt_object_t             mqtt_object = NULL;

    mqtt_connection_t*              p_mqtt_conn = NULL;

    do {

        if (0 != g_aws_connection) {

            p_aws = (wiced_aws_internal_handle_t*)g_aws_connection;

            mqtt_object = p_aws->mqtt.base;

            if(NULL != mqtt_object) {

                p_mqtt_conn = (mqtt_connection_t*)mqtt_object;

            }

            wiced_result = wiced_aws_disconnect(g_aws_connection);

            wiced_rtos_delay_milliseconds(5000);        // ★★★Additional Code (WICED_MQTT_EVENT_TYPE_DISCONNECTED event wait)

            wiced_result = wiced_rtos_deinit_semaphore(&s_event_semaphore);

            if(NULL != p_mqtt_conn) {

                wiced_result = mqtt_core_deinit(p_mqtt_conn);

            }

            if(NULL != mqtt_object) {

                free(mqtt_object);

            }

        }

        wiced_rtos_delay_milliseconds(3000);

        g_aws_connection = 0;

        if (WIFI_FALSE != s_mqtt_aws_init) {

            wiced_result = wiced_aws_deinit();

        }

        s_mqtt_aws_init = WIFI_FALSE;

        g_mqtt_connection = WIFI_FALSE;

    } while(0);

    return ret;

}

0 Likes

<Japanese>

以下の修正を行ったら、不具合が解消されたと思われます。

修正内容は、wiced_wps_enrollee関数の前のMQTT切断処理の「wiced_aws_disconnect」関数後に、ディレイを5秒間追加しました。(◆コード参照)

それにより、wiced_wps_enrollee関数が永久ループになる現象がなくなったのですが、関係性が不明であるため、質問があります。

◆QA

「wiced_aws_disconnect」関数後に、ディレイを5秒間追加したのは、WICED_MQTT_EVENT_TYPE_DISCONNECTEDイベントを待つためですが、MQTTイベントが、wiced_wps_enrollee関数の処理に影響を与えるものでしょうか。

考えられる原因がありましたら、教えてください。

0 Likes

Thanks for the details. There is some latency involved between calling wiced_aws_disconnect() which pushes the disconnect event to the RTOS queue with no wait and finally getting the WICED_AWS_EVENT_DISCONNECTED event. With the setting of no wait, it is not a blocking function. Which meaans that during this latency period, if wiced_wps_enrollee() is being called, it will call host_rtos_join_thread() which blocks the current thread until the thread specified in the function completes. This would have caused a deadlock. Adding the 5 second delay would have given sufficient time for wiced_aws_disconnect() to complete its operation. But instead of delay, you can also try using semaphore to ensure that the disconnect event is received. You can call wiced_rtos_get_semaphore() after wiced_aws_disconnect() and under case WICED_AWS_EVENT_DISCONNECTED, you can call wiced_rtos_set_semaphore(). This should avoid any potential deadlock issues.