pkarashchenko opened a new issue, #9695:
URL: https://github.com/apache/nuttx/issues/9695

   I'm having a system built in FLAT mode with `CONFIG_CANCELLATION_POINTS=y`. 
The system is running multiple tasks and one task is sending messages over CAN. 
There is send frame procedure that is opening a file descriptor -> calling 
write -> closing file descriptor. Sometimes that tasks is hitting a dead loop 
if it is canceled. The execution stocks in `open` call:
   `open()` -> `enter_cancellation_point()` -> `nx_vopen()` -> `file_vopen()` 
-> `inode_release()` -> `inode_lock()` -> `nxrmutex_lock()` -> `nxmutex_lock()` 
-> `_SEM_WAIT()/sem_wait() that is evaluated to sem_wait() because of #if 
!defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)` -> 
   ```
         do
           {
             ret = inode_lock();
   
             /* This only possible error is due to cancellation of the thread.
              * We need to try again anyway in this case, otherwise the
              * reference count would be wrong.
              */
   
             DEBUGASSERT(ret == OK || ret == -ECANCELED);
           }
         while (ret < 0);
   ```
   and 
   ```
   int sem_wait(FAR sem_t *sem)
   {
     int errcode;
     int ret;
   
     if (sem == NULL)
       {
         set_errno(EINVAL);
         return ERROR;
       }
   
     /* sem_wait() is a cancellation point */
   
     if (enter_cancellation_point())
       {
   #ifdef CONFIG_CANCELLATION_POINTS
         /* If there is a pending cancellation, then do not perform
          * the wait.  Exit now with ECANCELED.
          */
   
         errcode = ECANCELED;
         goto errout_with_cancelpt;
   #endif
       }
   ```
   So the nested cancellation point happens that `sem_wait()` return 
`ECANCELED` to `nxmutex_lock()` that is implemented as
   ```
   int nxmutex_lock(FAR mutex_t *mutex)
   {
     int ret;
   
     DEBUGASSERT(!nxmutex_is_hold(mutex));
     for (; ; )
       {
         /* Take the semaphore (perhaps waiting) */
   
         ret = _SEM_WAIT(&mutex->sem);
         if (ret >= 0)
           {
             mutex->holder = _SCHED_GETTID();
             break;
           }
   
         ret = _SEM_ERRVAL(ret);
         if (ret != -EINTR && ret != -ECANCELED)
           {
             break;
           }
       }
   
     return ret;
   }
   ```
   so task spinns forever in `nxmutex_lock()`.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to