@@ -477,6 +477,16 @@ int32 OS_Posix_InternalTaskCreate_Impl(pthread_t *pthr, osal_priority_t priority
477477 return (OS_ERROR );
478478 }
479479
480+ /*
481+ ** Set the thread to be joinable by default
482+ */
483+ return_code = pthread_attr_setdetachstate (& custom_attr , PTHREAD_CREATE_JOINABLE );
484+ if (return_code != 0 )
485+ {
486+ OS_DEBUG ("pthread_attr_setdetachstate error in OS_TaskCreate: %s\n" , strerror (return_code ));
487+ return (OS_ERROR );
488+ }
489+
480490 /*
481491 ** Test to see if the original main task scheduling priority worked.
482492 ** If so, then also set the attributes for this task. Otherwise attributes
@@ -541,12 +551,6 @@ int32 OS_Posix_InternalTaskCreate_Impl(pthread_t *pthr, osal_priority_t priority
541551 ** Do not treat anything bad that happens after this point as fatal.
542552 ** The task is running, after all - better to leave well enough alone.
543553 */
544- return_code = pthread_detach (* pthr );
545- if (return_code != 0 )
546- {
547- OS_DEBUG ("pthread_detach error in OS_TaskCreate: %s\n" , strerror (return_code ));
548- }
549-
550554 return_code = pthread_attr_destroy (& custom_attr );
551555 if (return_code != 0 )
552556 {
@@ -583,6 +587,33 @@ int32 OS_TaskCreate_Impl(const OS_object_token_t *token, uint32 flags)
583587 return return_code ;
584588} /* end OS_TaskCreate_Impl */
585589
590+ /*----------------------------------------------------------------
591+ *
592+ * Function: OS_TaskDetach_Impl
593+ *
594+ * Purpose: Implemented per internal OSAL API
595+ * See prototype for argument/return detail
596+ *
597+ *-----------------------------------------------------------------*/
598+ int32 OS_TaskDetach_Impl (const OS_object_token_t * token )
599+ {
600+ OS_impl_task_internal_record_t * impl ;
601+ int ret ;
602+
603+ impl = OS_OBJECT_TABLE_GET (OS_impl_task_table , * token );
604+
605+ ret = pthread_detach (impl -> id );
606+
607+ if (ret != 0 )
608+ {
609+ OS_DEBUG ("pthread_detach: Failed on Task ID = %lu, err = %s\n" ,
610+ OS_ObjectIdToInteger (OS_ObjectIdFromToken (token )), strerror (ret ));
611+ return OS_ERROR ;
612+ }
613+
614+ return OS_SUCCESS ;
615+ }
616+
586617/*----------------------------------------------------------------
587618 *
588619 * Function: OS_TaskMatch_Impl
@@ -616,6 +647,8 @@ int32 OS_TaskMatch_Impl(const OS_object_token_t *token)
616647int32 OS_TaskDelete_Impl (const OS_object_token_t * token )
617648{
618649 OS_impl_task_internal_record_t * impl ;
650+ void * retval ;
651+ int ret ;
619652
620653 impl = OS_OBJECT_TABLE_GET (OS_impl_task_table , * token );
621654
@@ -625,7 +658,35 @@ int32 OS_TaskDelete_Impl(const OS_object_token_t *token)
625658 ** to cancel here is that the thread ID is invalid because it already exited itself,
626659 ** and if that is true there is nothing wrong - everything is OK to continue normally.
627660 */
628- pthread_cancel (impl -> id );
661+ ret = pthread_cancel (impl -> id );
662+ if (ret != 0 )
663+ {
664+ OS_DEBUG ("pthread_cancel: Failed on Task ID = %lu, err = %s\n" ,
665+ OS_ObjectIdToInteger (OS_ObjectIdFromToken (token )), strerror (ret ));
666+
667+ /* fall through (will still return OS_SUCCESS) */
668+ }
669+ else
670+ {
671+ /*
672+ * Note that "pthread_cancel" is a request - and successful return above
673+ * only means that the cancellation request is pending.
674+ *
675+ * pthread_join() will wait until the thread has actually exited.
676+ *
677+ * This is important for CFE, as task deletion often occurs in
678+ * conjunction with an application reload - which means the next
679+ * call is likely to be OS_ModuleUnload(). So is critical that all
680+ * tasks potentially executing code within that module have actually
681+ * been stopped - not just pending cancellation.
682+ */
683+ ret = pthread_join (impl -> id , & retval );
684+ if (ret != 0 )
685+ {
686+ OS_DEBUG ("pthread_join: Failed on Task ID = %lu, err = %s\n" ,
687+ OS_ObjectIdToInteger (OS_ObjectIdFromToken (token )), strerror (ret ));
688+ }
689+ }
629690 return OS_SUCCESS ;
630691
631692} /* end OS_TaskDelete_Impl */
@@ -731,6 +792,17 @@ int32 OS_TaskRegister_Impl(osal_id_t global_task_id)
731792{
732793 int32 return_code ;
733794 OS_U32ValueWrapper_t arg ;
795+ int old_state ;
796+ int old_type ;
797+
798+ /*
799+ * Set cancel state=ENABLED, type=DEFERRED
800+ * This should be the default for new threads, but
801+ * setting explicitly to be sure that a pthread_join()
802+ * will work as expected in case this thread is deleted.
803+ */
804+ pthread_setcancelstate (PTHREAD_CANCEL_ENABLE , & old_state );
805+ pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED , & old_type );
734806
735807 arg .opaque_arg = 0 ;
736808 arg .id = global_task_id ;
0 commit comments