Kill MQX Task and close it's socket and recv() function

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Kill MQX Task and close it's socket and recv() function

Jump to solution
1,255 Views
Tim562
Senior Contributor I

Hi All,

     Does anyone know what would happen if one MQX task killed another MQX task that was listening for incoming socket data with a blocking recv() function call? Would MQX force recv() to return and close the socket properly? What if the task that is killed doesn't have ownership of the socket, will recv() still return and the socket close? Maybe recv() will return but the socket won't close? How about if the task that has ownership of the socket is closed, will that close the socket?

Are these statements true:

     1. Kill an MQX task that owns a socket and the socket is closed? ...Properly?

     2. Kill an MQX task with a blocking call to recv() in progress and MQX will force recv() to return?

     3. Kill a recv() task that doesn't own the socket and recv() will return but the socket will remain open?

     4. If a socket is closed because it's owning task is killed, a blocking call to recv() will return?

Thanks!

~Tim

Labels (1)
Tags (3)
0 Kudos
1 Solution
664 Views
Martin_
NXP Employee
NXP Employee

Tim,

recv() call means that the task sends a message to the TCP/IP task with a command

and command paramaters (parameters is a data structure on the task's stack) and then blocks itself via _task_block().

TCP/IP task receives messages and executes commands, specified by messages. For example for the stream socket recv(), the command is function TCP_receive().

When TCP/IP task shall unblock the recv() call, it does it by unblocking the task (remember it is blocked in _task_block()) by simply calling _task_ready(). Before that, it

has to return some information back to the caller task, such as how many data are available for reading, or status/error information, by writing this into the command parameters structure.

Now, when a task is blocked inside recv(), it means it has sent a message to the TCP/IP task and waits for unblocking. When you kill this task, the TCP/IP task is not aware,

so it doesn't know that is should cancel the command, and it will execute the command, it will write return information back on the task's stack (note the task's stack doesn't exists anymore after task destroy, so this can lead to very bad hard faults or data overwrite),and then it tries to _task_ready() a task that doesn't exist.

!!

It is absolutely not safe and not recommended to kill a task, that uses RTCS APIs, asynchronously from another task. Any RTCS application shall be designed in such a way

that the task does a return from the task's body after it has clean up resources.

!!

For the blocking recv() you can achieve this by using receive timeout, so recv() would return at least once per timeout and you can check application requests to stop.

This is how we have designed all new RTCS applications such as HTTPSRV. FTPSRV, websockets and so forth in RTCS 4.2.0. Morover, in RTCS 4.2.0 we have introduced 3rd socket set for select() function, which monitors unblock requests from other tasks. Thus, an application can wait in select() for either new data or application requests from other tasks (via SO_EXCEPTION setsockopt() function). We have used this in websockets implementation.

-Martin

View solution in original post

0 Kudos
4 Replies
665 Views
Martin_
NXP Employee
NXP Employee

Tim,

recv() call means that the task sends a message to the TCP/IP task with a command

and command paramaters (parameters is a data structure on the task's stack) and then blocks itself via _task_block().

TCP/IP task receives messages and executes commands, specified by messages. For example for the stream socket recv(), the command is function TCP_receive().

When TCP/IP task shall unblock the recv() call, it does it by unblocking the task (remember it is blocked in _task_block()) by simply calling _task_ready(). Before that, it

has to return some information back to the caller task, such as how many data are available for reading, or status/error information, by writing this into the command parameters structure.

Now, when a task is blocked inside recv(), it means it has sent a message to the TCP/IP task and waits for unblocking. When you kill this task, the TCP/IP task is not aware,

so it doesn't know that is should cancel the command, and it will execute the command, it will write return information back on the task's stack (note the task's stack doesn't exists anymore after task destroy, so this can lead to very bad hard faults or data overwrite),and then it tries to _task_ready() a task that doesn't exist.

!!

It is absolutely not safe and not recommended to kill a task, that uses RTCS APIs, asynchronously from another task. Any RTCS application shall be designed in such a way

that the task does a return from the task's body after it has clean up resources.

!!

For the blocking recv() you can achieve this by using receive timeout, so recv() would return at least once per timeout and you can check application requests to stop.

This is how we have designed all new RTCS applications such as HTTPSRV. FTPSRV, websockets and so forth in RTCS 4.2.0. Morover, in RTCS 4.2.0 we have introduced 3rd socket set for select() function, which monitors unblock requests from other tasks. Thus, an application can wait in select() for either new data or application requests from other tasks (via SO_EXCEPTION setsockopt() function). We have used this in websockets implementation.

-Martin

0 Kudos
664 Views
Tim562
Senior Contributor I

Thanks for the reply Martin, that's good info. I guess the only thing I don't understand is, what is the purpose of a task having ownership of a socket? What can a task that has ownership of a socket do, that another task without ownership, can't do? Can more than one task "own" a socket at the same time? Thanks!

Best Regards,

Tim

0 Kudos
664 Views
Martin_
NXP Employee
NXP Employee

Per my understanding, the purpose of the socket ownership was linked with RTCS_selectall() function. RTCS_selectall() blocks waiting on activity on all existing sockets. With socket ownership, the behavior is changed that it blocks waiting for activity on all socket that the calling task owns.

For new applications, we recommend to use POSIX-like select() function.

-Martin

0 Kudos
664 Views
Tim562
Senior Contributor I

Thank you!

Best Regards,

Tim Hutchinson

0 Kudos