rb_destroy(3)

bofc manual pages

rb_destroy(3)



 

NAME

rb_stop, rb_stop_signal, rb_destroy, rb_cleanup - functions to stop any locked threads in rb functions and free resources allocated by rb_new(3) and rb_init(3)  

SYNOPSIS

int rb_stop(struct rb *rb);
int rb_stop_signal(struct rb *rb, int signum);
int rb_destroy(struct rb *rb);
int rb_cleanup(struct rb *rb);

Feature Test Macro:

rb_stop():

ENABLE_THREADS

rb_stop_signal():

ENABLE_THREADS && ENABLE_POSIX_CALLS
 

DESCRIPTION

Function rb_stop(3) spawns thread (and then exits) that forces any locked thread to exit from rb_read(3) or rb_send(3). Also after this function is called, any call to rb_read(3) or rb_send(3) will result in error.

When ENABLE_THREADS and ENABLE_POSIX_CALLS are enabled and rb object was created with O_MULTITHREAD, rb_write(3) and rb_read(3) may be blocked in select() function and the only way for thread to leave blocked syscall is to send a signal. rb_stop(3) will send signum signal to all threads blocked in syscalls to release them so caller can join them in main thread. By default SIGUSR1 is sent. If you use this signal in your application, you can overwrite signal rb_stop(3) will send with rb_stop_signal(3) function.

Function rb_destroy(3) simply frees all resources allocated by rb_new(3). If rb_stop(3) was called before, function will stop spawned thread. After calling this, rb that was freed, cannot be used anymore without calling rb_new(3) first. Passing same rb object twice, will result in segmentation fault.

Function rb_cleanup(3) works same as rb_destroy(3) but should be called only on object initialized with rb_init(3) function.  

NOTES

Due to nature of pthread, you must be sure that no threads are calling any functions from librb before calling rb_destroy(3) or rb_cleanup(3). Failing to do so, will lead to deadlocks or crashes sooner or later.

If you cannot stop threads by yourself before calling rb_destroy(3), you can use rb_stop(3) function, to force all threads to exit, then join them, and after that destroy rb object. Look at below example.


    void *consumer(void *arg)
    {
        struct rb *rb = arg;
        int v, e;
        if (rb_read(rb, &v, 1) != 0)
        {
            if (errno == ECANCELED)
            {
                /* function was forced to exit, we should stop thread
                 * or at least make sure we don't access rb_* functions
                 * anymore
                 /


                 return NULL;
            }
        }
        /* more code */
    }


    void foo(void)
    {
        /* some code */
        for (int i = 0; i != 10; ++i)
        {
            pthread_create(&consumers[i], NULL, consumer, rb);
        }


        /* wait for some event */
        /* force all consumer threads to exit even if they are locked
         * in some conditional variables
         */
        rb_stop(rb);


        for (i = 0; i != 10; ++i)
        {
            /* make sure all consumer threads stopped, and none will access
             * any rb_* functions
             /
            pthread_join(consumers[i], NULL);
        }


        /* now it is safe to call rb_destroy function */
        rb_destroy(rb);
    }  

RETURN VALUES

Function will return 0 when all resources were freed, otherwise -1 is returned. If function returns -1 rb object is not modified.  

ERRORS

EINVAL
Passed rb is invalid (null).
EINVAL
Invalid signum passed in rb_stop_signal(3) function. Invalid as in signal does not exist on the system or SIGKILL or SIGSTOP was passed which cannot be caught. In that case signal is not changed.
ENOSYS
Function not implemented (feature macro not set)
 

SEE ALSO

rb_overview(7), rb_new(3), rb_init(3), rb_read(3), rb_discard(3), rb_recv(3), rb_write(3), rb_send(3), rb_posix_read(3), rb_posix_recv(3), rb_posix_write(3), rb_posix_send(3), rb_clear(3), rb_count(3), rb_space(3), rb_header_size(3), rb_array_size(3), rb_version(3)

bofc.pl

23 October 2018 (v1.1.0)

rb_destroy(3)