Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pthread cancel #5

Open
nslowell opened this issue Feb 26, 2020 · 4 comments
Open

pthread cancel #5

nslowell opened this issue Feb 26, 2020 · 4 comments
Labels
enhancement New feature or request feature request help wanted Extra attention is needed

Comments

@nslowell
Copy link

Where is pthread_cancel? Why is it not implemented?

@yuhui-zheng
Copy link
Contributor

Hello @nslowell,

Not all interfaces specified by POSIX Threading standard are implemented, since this project is a "lab project" nor we could claim we are "POSIX compliant". Though, if features are needed, we are happy to investigate what it takes to implement. In this case pthread_cancel() implementation is proposed in this PR #3 and some feedback is provided in the last comment. (And you are welcome to submit PRs, happy to take a look.)

@cobusve
Copy link
Member

cobusve commented Sep 30, 2020

The reason it is not implemented is that cancellation points are exceedingly difficult to decypher. See https://lwn.net/Articles/683118/ for some more information. The TLDR; for that is that threads may only be cancelled when a specific set of conditions are met according to the Posix standard, this is called a cancellation point, one example is that a thread may not be cancelled while it is holding on to a mutex or semaphore, but it gets quite a bit more complex than this.

If you look at this man page you will see the list of functions we will have to change to manage the cancellation points.
https://man7.org/linux/man-pages/man7/pthreads.7.html

Once we have completed this list we will be able to do pthread_cancel. It is a LOT of work.

Here is the list from the man-page:

Cancellation points
POSIX.1 specifies that certain functions must, and certain other
functions may, be cancellation points. If a thread is cancelable,
its cancelability type is deferred, and a cancellation request is
pending for the thread, then the thread is canceled when it calls a
function that is a cancellation point.

   The following functions are required to be cancellation points by
   POSIX.1-2001 and/or POSIX.1-2008:

       accept()
       aio_suspend()
       clock_nanosleep()
       close()
       connect()
       creat()
       fcntl() F_SETLKW
       fdatasync()
       fsync()
       getmsg()
       getpmsg()
       lockf() F_LOCK
       mq_receive()
       mq_send()
       mq_timedreceive()
       mq_timedsend()
       msgrcv()
       msgsnd()
       msync()
       nanosleep()
       open()
       openat() [Added in POSIX.1-2008]
       pause()
       poll()
       pread()
       pselect()
       pthread_cond_timedwait()
       pthread_cond_wait()
       pthread_join()
       pthread_testcancel()
       putmsg()
       putpmsg()
       pwrite()
       read()
       readv()
       recv()
       recvfrom()
       recvmsg()
       select()
       sem_timedwait()
       sem_wait()
       send()
       sendmsg()
       sendto()
       sigpause() [POSIX.1-2001 only (moves to "may" list in POSIX.1-2008)]
       sigsuspend()
       sigtimedwait()
       sigwait()
       sigwaitinfo()
       sleep()
       system()
       tcdrain()
       usleep() [POSIX.1-2001 only (function removed in POSIX.1-2008)]
       wait()
       waitid()
       waitpid()
       write()
       writev()

   The following functions may be cancellation points according to
   POSIX.1-2001 and/or POSIX.1-2008:

       access()
       asctime()
       asctime_r()
       catclose()
       catgets()
       catopen()
       chmod() [Added in POSIX.1-2008]
       chown() [Added in POSIX.1-2008]
       closedir()
       closelog()
       ctermid()
       ctime()
       ctime_r()
       dbm_close()
       dbm_delete()
       dbm_fetch()
       dbm_nextkey()
       dbm_open()
       dbm_store()
       dlclose()
       dlopen()
       dprintf() [Added in POSIX.1-2008]
       endgrent()
       endhostent()
       endnetent()
       endprotoent()
       endpwent()
       endservent()
       endutxent()
       faccessat() [Added in POSIX.1-2008]
       fchmod() [Added in POSIX.1-2008]
       fchmodat() [Added in POSIX.1-2008]
       fchown() [Added in POSIX.1-2008]
       fchownat() [Added in POSIX.1-2008]
       fclose()
       fcntl() (for any value of cmd argument)
       fflush()
       fgetc()
       fgetpos()
       fgets()
       fgetwc()
       fgetws()
       fmtmsg()
       fopen()
       fpathconf()
       fprintf()
       fputc()
       fputs()
       fputwc()
       fputws()
       fread()
       freopen()
       fscanf()
       fseek()
       fseeko()
       fsetpos()
       fstat()
       fstatat() [Added in POSIX.1-2008]
       ftell()
       ftello()
       ftw()
       futimens() [Added in POSIX.1-2008]
       fwprintf()
       fwrite()
       fwscanf()
       getaddrinfo()
       getc()
       getc_unlocked()
       getchar()
       getchar_unlocked()
       getcwd()
       getdate()
       getdelim() [Added in POSIX.1-2008]
       getgrent()
       getgrgid()
       getgrgid_r()
       getgrnam()
       getgrnam_r()
       gethostbyaddr() [SUSv3 only (function removed in POSIX.1-2008)]
       gethostbyname() [SUSv3 only (function removed in POSIX.1-2008)]
       gethostent()
       gethostid()
       gethostname()
       getline() [Added in POSIX.1-2008]
       getlogin()
       getlogin_r()
       getnameinfo()
       getnetbyaddr()
       getnetbyname()
       getnetent()
       getopt() (if opterr is nonzero)
       getprotobyname()
       getprotobynumber()
       getprotoent()
       getpwent()
       getpwnam()
       getpwnam_r()
       getpwuid()
       getpwuid_r()
       gets()
       getservbyname()
       getservbyport()
       getservent()
       getutxent()
       getutxid()
       getutxline()
       getwc()
       getwchar()
       getwd() [SUSv3 only (function removed in POSIX.1-2008)]
       glob()
       iconv_close()
       iconv_open()
       ioctl()
       link()
       linkat() [Added in POSIX.1-2008]
       lio_listio() [Added in POSIX.1-2008]
       localtime()
       localtime_r()
       lockf() [Added in POSIX.1-2008]
       lseek()
       lstat()
       mkdir() [Added in POSIX.1-2008]
       mkdirat() [Added in POSIX.1-2008]
       mkdtemp() [Added in POSIX.1-2008]
       mkfifo() [Added in POSIX.1-2008]
       mkfifoat() [Added in POSIX.1-2008]
       mknod() [Added in POSIX.1-2008]
       mknodat() [Added in POSIX.1-2008]
       mkstemp()
       mktime()
       nftw()
       opendir()
       openlog()
       pathconf()
       pclose()
       perror()
       popen()
       posix_fadvise()
       posix_fallocate()
       posix_madvise()
       posix_openpt()
       posix_spawn()
       posix_spawnp()
       posix_trace_clear()
       posix_trace_close()
       posix_trace_create()
       posix_trace_create_withlog()
       posix_trace_eventtypelist_getnext_id()
       posix_trace_eventtypelist_rewind()
       posix_trace_flush()
       posix_trace_get_attr()
       posix_trace_get_filter()
       posix_trace_get_status()
       posix_trace_getnext_event()
       posix_trace_open()
       posix_trace_rewind()
       posix_trace_set_filter()
       posix_trace_shutdown()
       posix_trace_timedgetnext_event()
       posix_typed_mem_open()
       printf()
       psiginfo() [Added in POSIX.1-2008]
       psignal() [Added in POSIX.1-2008]
       pthread_rwlock_rdlock()
       pthread_rwlock_timedrdlock()
       pthread_rwlock_timedwrlock()
       pthread_rwlock_wrlock()
       putc()
       putc_unlocked()
       putchar()
       putchar_unlocked()
       puts()
       pututxline()
       putwc()
       putwchar()
       readdir()
       readdir_r()
       readlink() [Added in POSIX.1-2008]
       readlinkat() [Added in POSIX.1-2008]
       remove()
       rename()
       renameat() [Added in POSIX.1-2008]
       rewind()
       rewinddir()
       scandir() [Added in POSIX.1-2008]
       scanf()
       seekdir()
       semop()
       setgrent()
       sethostent()
       setnetent()
       setprotoent()
       setpwent()
       setservent()
       setutxent()
       sigpause() [Added in POSIX.1-2008]
       stat()
       strerror()
       strerror_r()
       strftime()
       symlink()
       symlinkat() [Added in POSIX.1-2008]
       sync()
       syslog()
       tmpfile()
       tmpnam()
       ttyname()
       ttyname_r()
       tzset()
       ungetc()
       ungetwc()
       unlink()
       unlinkat() [Added in POSIX.1-2008]
       utime() [Added in POSIX.1-2008]
       utimensat() [Added in POSIX.1-2008]
       utimes() [Added in POSIX.1-2008]
       vdprintf() [Added in POSIX.1-2008]
       vfprintf()
       vfwprintf()
       vprintf()
       vwprintf()
       wcsftime()
       wordexp()
       wprintf()
       wscanf()

@cobusve cobusve added enhancement New feature or request help wanted Extra attention is needed labels Sep 30, 2020
@yuhui-zheng
Copy link
Contributor

yuhui-zheng commented Oct 1, 2020

Since I'm on this thread, here's my opinion.

  • Above list is quite interesting, as some of the interfaces are not practical for FreeRTOS.
    Randomly picking one or two — read/readv read from a file; getpwnam/getpwnam_r search user database for a name. Either it's trying to expand from current POSIX threading implementation to include IO/file system/..., or there's some misunderstanding.

  • Having a complete POSIX support does not really intertwine with thread cancellation points/states/APIs. In this case, what it really takes to support thread cancellation is to update pthread data structure to track thread cancellation state. And update related APIs to set cancellation state at cancellation points.
    For this point, see TI-POSIX's approach http://software-dl.ti.com/simplelink/esd/simplelink_msp432_sdk/2.40.00.10/docs/tiposix/Users_Guide.html.

The design was shared in email some time ago, posting that would be a good starting point to get community contribution. And of course it is up to the FreeRTOS team to define the scope for FreeRTOS-POSIX, as POSIX alone is huge. I'm dropping from this conversation now.

@cobusve
Copy link
Member

cobusve commented Oct 2, 2020

@yuhui-zheng , I am not sure I understand what you mean with regard to "read/readv" applicability to FreeRTOS above? As you know a "stream" in C is called a "FILE" (for historical reasons) and functions like scanf and printf will typically make use of these IO streams, which seems very relevant to FreeRTOS. We use it with serial ports on devices all of the time?

I am also not sure what you mean by "In this case, what it really takes to support thread cancellation is to update pthread data structure to track thread cancellation state.", but your comments for sure has me hopeful. If you have a suggestion how we could implement this relatively simply (which it sure sounds like you have) then I would love to give it a try!

From what I can gather a call to pthread_cancel must cause a target thread to - at a later point in time, and in the context of the target thread (not the caller) kill itself, including running any pushed cleanup handlers. If the target thread is suspended at the time of the request, due to something like e.g. pthread_cond_wait, the target thread shoud be awakened and it should then cancel itself when next scheduled.

One curiosity here is that pthread_mutex_lock() is NOT a cancellation point, which means that if the target thread is blocked waiting on a mutex you will need a mechanism to unblock it conditionally depending on whether the mutex it is blocked by is a cancellation point mutex or a non-cancellation point mutex.

I am not saying that this is not possible, of course it is possible, but this seems rather hard to implement without doing a lot more than simply tracking cancellation state?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feature request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

4 participants