Changeset d3ce33fa in mainline for uspace/lib/posix/signal.c


Ignore:
Timestamp:
2011-07-05T19:01:18Z (13 years ago)
Author:
Jiří Zárevúcky <zarevucky.jiri@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d9eaa43
Parents:
4f86fa3
Message:

signal.h: Add some functions and implementations

File:
1 edited

Legend:

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

    r4f86fa3 rd3ce33fa  
    3737#include "signal.h"
    3838#include "internal/common.h"
     39#include "limits.h"
     40#include "stdlib.h"
     41#include "string.h"
     42#include "errno.h"
     43
     44#include "libc/fibril_synch.h"
     45#include "libc/task.h"
     46
     47/* Used to serialize signal handling. */
     48static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
     49
     50static posix_sigset_t _signal_mask = 0;
     51
     52#define DEFAULT_HANDLER { .sa_handler = SIG_DFL, \
     53    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
     54
     55static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
     56        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     57        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     58        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     59        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     60        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     61        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     62        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER
     63};
     64
     65void __posix_default_signal_handler(int signo)
     66{
     67        switch (signo) {
     68        case SIGABRT:
     69                abort();
     70        case SIGQUIT:
     71                fprintf(stderr, "Quit signal raised. Exiting.");
     72                exit(EXIT_FAILURE);
     73        case SIGINT:
     74                fprintf(stderr, "Interrupt signal caught. Exiting.");
     75                exit(EXIT_FAILURE);
     76        case SIGTERM:
     77                fprintf(stderr, "Termination signal caught. Exiting.");
     78                exit(EXIT_FAILURE);
     79        case SIGSTOP:
     80                fprintf(stderr, "Stop signal caught, but unsupported. Ignoring.");
     81                break;
     82        case SIGKILL:
     83                /* This will only occur when raise or similar is called. */
     84                /* Commit suicide. */
     85                task_kill(task_get_id());
     86               
     87                /* Should not be reached. */
     88                abort();
     89        case SIGFPE:
     90        case SIGBUS:
     91        case SIGILL:
     92        case SIGSEGV:
     93                posix_psignal(signo, "Hardware exception raised by user code");
     94                abort();
     95        case SIGSYS:
     96        case SIGXCPU:
     97        case SIGXFSZ:
     98        case SIGTRAP:
     99        case SIGHUP:
     100        case SIGPIPE:
     101        case SIGPOLL:
     102        case SIGURG:
     103        case SIGTSTP:
     104        case SIGTTIN:
     105        case SIGTTOU:
     106                posix_psignal(signo, "Unsupported signal caught");
     107                abort();
     108        case SIGCHLD:
     109        case SIGUSR1:
     110        case SIGUSR2:
     111        case SIGALRM:
     112        case SIGVTALRM:
     113        case SIGPROF:
     114        case SIGCONT:
     115                /* ignored */
     116                break;
     117        }
     118}
     119
     120void __posix_hold_signal_handler(int signo)
     121{
     122        /* Nothing */
     123}
     124
     125void __posix_ignore_signal_handler(int signo)
     126{
     127        /* Nothing */
     128}
     129
     130
     131int posix_sigemptyset(posix_sigset_t *set)
     132{
     133        assert(set != NULL);
     134
     135        *set = 0;
     136        return 0;
     137}
     138
     139int posix_sigfillset(posix_sigset_t *set)
     140{
     141        assert(set != NULL);
     142
     143        *set = UINT32_MAX;
     144        return 0;
     145}
     146
     147int posix_sigaddset(posix_sigset_t *set, int signo)
     148{
     149        assert(set != NULL);
     150
     151        *set |= (1 << signo);
     152        return 0;
     153}
     154
     155int posix_sigdelset(posix_sigset_t *set, int signo)
     156{
     157        assert(set != NULL);
     158
     159        *set &= ~(1 << signo);
     160        return 0;
     161}
     162
     163int posix_sigismember(const posix_sigset_t *set, int signo)
     164{
     165        assert(set != NULL);
     166       
     167        return (*set & (1 << signo)) != 0;
     168}
     169
     170static void _sigaction_unsafe(int sig, const struct posix_sigaction *restrict act,
     171    struct posix_sigaction *restrict oact)
     172{
     173        if (oact != NULL) {
     174                memcpy(oact, &_signal_actions[sig],
     175                    sizeof(struct posix_sigaction));
     176        }
     177
     178        if (act != NULL) {
     179                memcpy(&_signal_actions[sig], act,
     180                    sizeof(struct posix_sigaction));
     181        }
     182}
     183
     184int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     185    struct posix_sigaction *restrict oact)
     186{
     187        if (sig > _TOP_SIGNAL || (act != NULL &&
     188            (sig == SIGKILL || sig == SIGSTOP))) {
     189                errno = EINVAL;
     190                return -1;
     191        }
     192
     193        if (sig > _TOP_CATCHABLE_SIGNAL) {
     194                posix_psignal(sig,
     195                    "WARNING: registering handler for a partially"
     196                    " or fully unsupported signal. This handler may only be"
     197                    " invoked by the raise() function, which may not be what"
     198                    " the application developer intended.\nSignal name");
     199        }
     200
     201        fibril_mutex_lock(&_signal_mutex);
     202        _sigaction_unsafe(sig, act, oact);
     203        fibril_mutex_unlock(&_signal_mutex);
     204
     205        return 0;
     206}
    39207
    40208void (*posix_signal(int sig, void (*func)(int)))(int)
    41209{
    42         // TODO
    43         not_implemented();
     210        struct posix_sigaction new = {
     211                .sa_handler = func,
     212                .sa_mask = 0,
     213                .sa_flags = 0,
     214                .sa_sigaction = NULL
     215        };
     216        struct posix_sigaction old;
     217        if (posix_sigaction(sig, func == NULL ? NULL : &new, &old) == 0) {
     218                return old.sa_handler;
     219        } else {
     220                return SIG_ERR;
     221        }
     222}
     223
     224static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     225{
     226        assert(signo >= 0 && signo <= _TOP_SIGNAL);
     227        assert(siginfo != NULL);
     228
     229        fibril_mutex_lock(&_signal_mutex);
     230
     231        struct posix_sigaction action = _signal_actions[signo];
     232
     233        if (posix_sigismember(&_signal_mask, signo) ||
     234            action.sa_handler == SIG_HOLD) {
     235                // TODO: queue signal
     236                fibril_mutex_unlock(&_signal_mutex);
     237                return -1;
     238        }
     239
     240        /* Modifying signal mask is unnecessary,
     241         * signal handling is serialized.
     242         */
     243
     244        if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
     245                _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
     246        };
     247
     248        if (action.sa_flags & SA_SIGINFO) {
     249                assert(action.sa_sigaction != NULL);
     250                action.sa_sigaction(signo, siginfo, NULL);
     251        } else {
     252                assert(action.sa_handler != NULL);
     253                action.sa_handler(signo);
     254        }
     255
     256        fibril_mutex_unlock(&_signal_mutex);
     257
     258        return 0;
    44259}
    45260
    46261int posix_raise(int sig)
    47262{
    48         // TODO
    49         not_implemented();
    50 }
    51 
    52 int posix_kill(posix_pid_t pid, int sig)
    53 {
    54         // TODO
    55         not_implemented();
    56 }
    57 
    58 int posix_sigaddset(posix_sigset_t *set, int signo)
    59 {
    60         // TODO
    61         not_implemented();
    62 }
    63 
    64 int posix_sigemptyset(posix_sigset_t *set)
    65 {
    66         // TODO
    67         not_implemented();
     263        if (sig >= 0 && sig <= _TOP_SIGNAL) {
     264                posix_siginfo_t siginfo = {
     265                        .si_signo = sig,
     266                        .si_code = SI_USER
     267                };
     268                return _raise_sigaction(sig, &siginfo);
     269        } else {
     270                errno = EINVAL;
     271                return -1;
     272        }
     273}
     274
     275int posix_kill(posix_pid_t pid, int signo)
     276{
     277        if (pid < 1) {
     278                // TODO
     279                errno = ENOTSUP;
     280                return -1;
     281        }
     282
     283        if (pid == task_get_id()) {
     284                return posix_raise(signo);
     285        }
     286
     287        if (pid > _TOP_SIGNAL) {
     288                errno = EINVAL;
     289                return -1;
     290        }
     291
     292        switch (signo) {
     293        case SIGKILL:
     294                task_kill(pid);
     295                break;
     296        default:
     297                /* Nothing else supported yet. */
     298                errno = ENOTSUP;
     299                return -1;
     300        }
     301
     302        return 0;
     303}
     304
     305int posix_killpg(posix_pid_t pid, int sig)
     306{
     307        assert(pid > 1);
     308        return posix_kill(-pid, sig);
     309}
     310
     311void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
     312{
     313        assert(pinfo != NULL);
     314        posix_psignal(pinfo->si_signo, message);
     315        // TODO: print si_code
     316}
     317
     318void posix_psignal(int signum, const char *message)
     319{
     320        char *sigmsg = posix_strsignal(signum);
     321        if (message == NULL || *message == '\0') {
     322                fprintf(stderr, "%s\n", sigmsg);
     323        } else {
     324                fprintf(stderr, "%s: %s\n", message, sigmsg);
     325        }
     326}
     327
     328int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     329    posix_sigset_t *restrict oset)
     330{
     331        fibril_mutex_lock(&_signal_mutex);
     332
     333        if (oset != NULL) {
     334                *oset = _signal_mask;
     335        }
     336        if (set != NULL) {
     337                switch (how) {
     338                case SIG_BLOCK:
     339                        _signal_mask |= *set;
     340                        break;
     341                case SIG_UNBLOCK:
     342                        _signal_mask &= ~*set;
     343                        break;
     344                case SIG_SETMASK:
     345                        _signal_mask = *set;
     346                        break;
     347                default:
     348                        fibril_mutex_unlock(&_signal_mutex);
     349                        return EINVAL;
     350                }
     351        }
     352
     353        // TODO: queued signal handling
     354
     355        fibril_mutex_unlock(&_signal_mutex);
     356
     357        return 0;
    68358}
    69359
     
    71361    posix_sigset_t *restrict oset)
    72362{
    73         // TODO
    74         not_implemented();
     363        int result = posix_thread_sigmask(how, set, oset);
     364        if (result != 0) {
     365                errno = result;
     366                return -1;
     367        }
     368        return 0;
    75369}
    76370
Note: See TracChangeset for help on using the changeset viewer.