Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/posix/signal.c

    r4419c34 rf215bb5f  
    4545#include "libc/task.h"
    4646
    47 /* This file implements a fairly dumb and incomplete "simulation" of
    48  * POSIX signals. Since HelenOS doesn't support signals and mostly doesn't
    49  * have any equivalent functionality, most of the signals are useless. The
    50  * main purpose of this implementation is thus to help port applications using
    51  * signals with minimal modification, but if the application uses signals for
    52  * anything non-trivial, it's quite probable it won't work properly even if
    53  * it builds without problems.
    54  */
     47// TODO: documentation
    5548
    5649/* Used to serialize signal handling. */
    5750static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
    5851
    59 static LIST_INITIALIZE(_signal_queue);
    60 
    6152static posix_sigset_t _signal_mask = 0;
    6253
     
    6455    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
    6556
    66 /* Actions associated with each signal number. */
    6757static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
    6858        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     
    136126}
    137127
    138 /** Just an empty function to get an unique pointer value for comparison.
     128/**
    139129 *
    140130 * @param signo
     
    145135}
    146136
    147 /** Empty function to be used as ignoring handler.
     137/**
    148138 *
    149139 * @param signo
     
    154144}
    155145
    156 /** Clear the signal set.
    157  *
    158  * @param set Pointer to the signal set.
    159  * @return Always returns zero.
     146/**
     147 *
     148 * @param set
     149 * @return
    160150 */
    161151int posix_sigemptyset(posix_sigset_t *set)
     
    167157}
    168158
    169 /** Fill the signal set (i.e. add all signals).
    170  *
    171  * @param set Pointer to the signal set.
    172  * @return Always returns zero.
     159/**
     160 *
     161 * @param set
     162 * @return
    173163 */
    174164int posix_sigfillset(posix_sigset_t *set)
     
    180170}
    181171
    182 /** Add a signal to the set.
    183  *
    184  * @param set Pointer to the signal set.
    185  * @param signo Signal number to add.
    186  * @return Always returns zero.
     172/**
     173 *
     174 * @param set
     175 * @param signo
     176 * @return
    187177 */
    188178int posix_sigaddset(posix_sigset_t *set, int signo)
     
    194184}
    195185
    196 /** Delete a signal from the set.
    197  *
    198  * @param set Pointer to the signal set.
    199  * @param signo Signal number to remove.
    200  * @return Always returns zero.
     186/**
     187 *
     188 * @param set
     189 * @param signo
     190 * @return
    201191 */
    202192int posix_sigdelset(posix_sigset_t *set, int signo)
     
    208198}
    209199
    210 /** Inclusion test for a signal set.
    211  *
    212  * @param set Pointer to the signal set.
    213  * @param signo Signal number to query.
    214  * @return 1 if the signal is in the set, 0 otherwise.
     200/**
     201 *
     202 * @param set
     203 * @param signo
     204 * @return
    215205 */
    216206int posix_sigismember(const posix_sigset_t *set, int signo)
     
    221211}
    222212
    223 /** Unsafe variant of the sigaction() function.
    224  *  Doesn't do any checking of its arguments and
    225  *  does not deal with thread-safety.
     213/**
    226214 *
    227215 * @param sig
     
    243231}
    244232
    245 /** Sets a new action for the given signal number.
    246  *
    247  * @param sig Signal number to set action for.
    248  * @param act If not NULL, contents of this structure are
    249  *     used as the new action for the signal.
    250  * @param oact If not NULL, the original action associated with the signal
    251  *     is stored in the structure pointer to.
    252  * @return -1 with errno set on failure, 0 on success.
     233/**
     234 *
     235 * @param sig
     236 * @param act
     237 * @param oact
     238 * @return
    253239 */
    254240int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     
    266252                    " or fully unsupported signal. This handler may only be"
    267253                    " invoked by the raise() function, which may not be what"
    268                     " the application developer intended");
     254                    " the application developer intended.\nSignal name");
    269255        }
    270256
     
    276262}
    277263
    278 /** Sets a new handler for the given signal number.
    279  *
    280  * @param sig Signal number to set handler for.
    281  * @param func Handler function.
    282  * @return SIG_ERR on failure, original handler on success.
     264/**
     265 *
     266 * @param sig
     267 * @param func
     268 * @return
    283269 */
    284270void (*posix_signal(int sig, void (*func)(int)))(int)
     
    298284}
    299285
    300 typedef struct {
    301         link_t link;
    302         int signo;
    303         posix_siginfo_t siginfo;
    304 } signal_queue_item;
    305 
    306 /** Queue blocked signal.
    307  *
    308  * @param signo Signal number.
    309  * @param siginfo Additional information about the signal.
    310  */
    311 static void _queue_signal(int signo, posix_siginfo_t *siginfo)
     286/**
     287 *
     288 * @param signo
     289 * @param siginfo
     290 * @return
     291 */
     292static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
    312293{
    313294        assert(signo >= 0 && signo <= _TOP_SIGNAL);
    314295        assert(siginfo != NULL);
    315        
    316         signal_queue_item *item = malloc(sizeof(signal_queue_item));
    317         link_initialize(&(item->link));
    318         item->signo = signo;
    319         memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
    320         list_append(&(item->link), &_signal_queue);
    321 }
    322 
    323 
    324 /** Executes an action associated with the given signal.
    325  *
    326  * @param signo Signal number.
    327  * @param siginfo Additional information about the circumstances of this raise.
    328  * @return 0 if the action has been successfully executed. -1 if the signal is
    329  *     blocked.
    330  */
    331 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
    332 {
    333         assert(signo >= 0 && signo <= _TOP_SIGNAL);
    334         assert(siginfo != NULL);
    335296
    336297        fibril_mutex_lock(&_signal_mutex);
     
    340301        if (posix_sigismember(&_signal_mask, signo) ||
    341302            action.sa_handler == SIG_HOLD) {
    342                 _queue_signal(signo, siginfo);
     303                // TODO: queue signal
    343304                fibril_mutex_unlock(&_signal_mutex);
    344305                return -1;
     
    351312        if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
    352313                _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
    353         }
     314        };
    354315
    355316        if (action.sa_flags & SA_SIGINFO) {
     
    366327}
    367328
    368 /** Raise all unblocked previously queued signals.
    369  */
    370 static void _dequeue_unblocked_signals()
    371 {
    372         link_t *iterator = _signal_queue.head.next;
    373         link_t *next;
    374        
    375         while (iterator != &(_signal_queue).head) {
    376                 next = iterator->next;
    377                
    378                 signal_queue_item *item =
    379                     list_get_instance(iterator, signal_queue_item, link);
    380                
    381                 if (!posix_sigismember(&_signal_mask, item->signo) &&
    382                     _signal_actions[item->signo].sa_handler != SIG_HOLD) {
    383                         list_remove(&(item->link));
    384                         _raise_sigaction(item->signo, &(item->siginfo));
    385                         free(item);
    386                 }
    387                
    388                 iterator = next;
    389         }
    390 }
    391 
    392 /** Raise a signal for the calling process.
    393  *
    394  * @param sig Signal number.
    395  * @return -1 with errno set on failure, 0 on success.
     329/**
     330 *
     331 * @param sig
     332 * @return
    396333 */
    397334int posix_raise(int sig)
     
    409346}
    410347
    411 /** Raises a signal for a selected process.
    412  *
    413  * @param pid PID of the process for which the signal shall be raised.
    414  * @param signo Signal to raise.
    415  * @return -1 with errno set on failure (possible errors include unsupported
    416  *     action, invalid signal number, lack of permissions, etc.), 0 on success.
     348/**
     349 *
     350 * @param pid
     351 * @param signo
     352 * @return
    417353 */
    418354int posix_kill(posix_pid_t pid, int signo)
     
    424360        }
    425361
    426         if (signo > _TOP_SIGNAL) {
    427                 errno = EINVAL;
    428                 return -1;
    429         }
    430 
    431362        if (pid == (posix_pid_t) task_get_id()) {
    432363                return posix_raise(signo);
     364        }
     365
     366        if (pid > _TOP_SIGNAL) {
     367                errno = EINVAL;
     368                return -1;
    433369        }
    434370
     
    446382}
    447383
    448 /** Send a signal to a process group. Always fails at the moment because of
    449  *  lack of this functionality in HelenOS.
    450  *
    451  * @param pid PID of the process group.
    452  * @param sig Signal number.
    453  * @return -1 on failure, 0 on success (see kill()).
     384/**
     385 *
     386 * @param pid
     387 * @param sig
     388 * @return
    454389 */
    455390int posix_killpg(posix_pid_t pid, int sig)
     
    459394}
    460395
    461 /** Outputs information about the signal to the standard error stream.
    462  *
    463  * @param pinfo SigInfo struct to write.
    464  * @param message String to output alongside human-readable signal description.
     396/**
     397 *
     398 * @param pinfo
     399 * @param message
    465400 */
    466401void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
     
    471406}
    472407
    473 /** Outputs information about the signal to the standard error stream.
    474  *
    475  * @param signum Signal number.
    476  * @param message String to output alongside human-readable signal description.
     408/**
     409 *
     410 * @param signum
     411 * @param message
    477412 */
    478413void posix_psignal(int signum, const char *message)
     
    486421}
    487422
    488 /** Manipulate the signal mask of the calling thread.
    489  *
    490  * @param how What to do with the mask.
    491  * @param set Signal set to work with.
    492  * @param oset If not NULL, the original signal mask is coppied here.
    493  * @return 0 success, errorcode on failure.
     423/**
     424 *
     425 * @param how
     426 * @param set
     427 * @param oset
     428 * @return
    494429 */
    495430int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     
    517452                }
    518453        }
    519        
    520         _dequeue_unblocked_signals();
     454
     455        // TODO: queued signal handling
    521456
    522457        fibril_mutex_unlock(&_signal_mutex);
     
    525460}
    526461
    527 /** Manipulate the signal mask of the process.
    528  *
    529  * @param how What to do with the mask.
    530  * @param set Signal set to work with.
    531  * @param oset If not NULL, the original signal mask is coppied here.
    532  * @return 0 on success, -1 with errno set on failure.
     462/**
     463 *
     464 * @param how
     465 * @param set
     466 * @param oset
     467 * @return
    533468 */
    534469int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
Note: See TracChangeset for help on using the changeset viewer.