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


Ignore:
Timestamp:
2011-08-18T08:00:42Z (13 years ago)
Author:
Petr Koupy <petr.koupy@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
a92cf94f
Parents:
0f963cb (diff), c53a705 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge libposix changes.

File:
1 edited

Legend:

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

    r0f963cb ree24574  
    4545#include "libc/task.h"
    4646
    47 // TODO: documentation
     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 */
    4855
    4956/* Used to serialize signal handling. */
    5057static FIBRIL_MUTEX_INITIALIZE(_signal_mutex);
    5158
     59static LIST_INITIALIZE(_signal_queue);
     60
    5261static posix_sigset_t _signal_mask = 0;
    5362
     
    5564    .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL }
    5665
     66/* Actions associated with each signal number. */
    5767static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = {
    5868        DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER,
     
    127137
    128138/**
    129  *
    130  * @param signo
     139 * Just an empty function to get an unique pointer value for comparison.
     140 *
     141 * @param signo Signal number.
    131142 */
    132143void __posix_hold_signal_handler(int signo)
     
    136147
    137148/**
    138  *
    139  * @param signo
     149 * Empty function to be used as ignoring handler.
     150 *
     151 * @param signo Signal number.
    140152 */
    141153void __posix_ignore_signal_handler(int signo)
     
    145157
    146158/**
    147  *
    148  * @param set
    149  * @return
     159 * Clear the signal set.
     160 *
     161 * @param set Pointer to the signal set.
     162 * @return Always returns zero.
    150163 */
    151164int posix_sigemptyset(posix_sigset_t *set)
     
    158171
    159172/**
    160  *
    161  * @param set
    162  * @return
     173 * Fill the signal set (i.e. add all signals).
     174 *
     175 * @param set Pointer to the signal set.
     176 * @return Always returns zero.
    163177 */
    164178int posix_sigfillset(posix_sigset_t *set)
     
    171185
    172186/**
    173  *
    174  * @param set
    175  * @param signo
    176  * @return
     187 * Add a signal to the set.
     188 *
     189 * @param set Pointer to the signal set.
     190 * @param signo Signal number to add.
     191 * @return Always returns zero.
    177192 */
    178193int posix_sigaddset(posix_sigset_t *set, int signo)
     
    185200
    186201/**
    187  *
    188  * @param set
    189  * @param signo
    190  * @return
     202 * Delete a signal from the set.
     203 *
     204 * @param set Pointer to the signal set.
     205 * @param signo Signal number to remove.
     206 * @return Always returns zero.
    191207 */
    192208int posix_sigdelset(posix_sigset_t *set, int signo)
     
    199215
    200216/**
    201  *
    202  * @param set
    203  * @param signo
    204  * @return
     217 * Inclusion test for a signal set.
     218 *
     219 * @param set Pointer to the signal set.
     220 * @param signo Signal number to query.
     221 * @return 1 if the signal is in the set, 0 otherwise.
    205222 */
    206223int posix_sigismember(const posix_sigset_t *set, int signo)
     
    212229
    213230/**
     231 * Unsafe variant of the sigaction() function.
     232 * Doesn't do any checking of its arguments and
     233 * does not deal with thread-safety.
    214234 *
    215235 * @param sig
     
    232252
    233253/**
    234  *
    235  * @param sig
    236  * @param act
    237  * @param oact
    238  * @return
     254 * Sets a new action for the given signal number.
     255 *
     256 * @param sig Signal number to set action for.
     257 * @param act If not NULL, contents of this structure are
     258 *     used as the new action for the signal.
     259 * @param oact If not NULL, the original action associated with the signal
     260 *     is stored in the structure pointer to.
     261 * @return -1 with errno set on failure, 0 on success.
    239262 */
    240263int posix_sigaction(int sig, const struct posix_sigaction *restrict act,
     
    263286
    264287/**
    265  *
    266  * @param sig
    267  * @param func
    268  * @return
     288 * Sets a new handler for the given signal number.
     289 *
     290 * @param sig Signal number to set handler for.
     291 * @param func Handler function.
     292 * @return SIG_ERR on failure, original handler on success.
    269293 */
    270294void (*posix_signal(int sig, void (*func)(int)))(int)
     
    284308}
    285309
    286 /**
    287  *
    288  * @param signo
    289  * @param siginfo
    290  * @return
    291  */
    292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     310typedef struct {
     311        link_t link;
     312        int signo;
     313        posix_siginfo_t siginfo;
     314} signal_queue_item;
     315
     316/**
     317 * Queue blocked signal.
     318 *
     319 * @param signo Signal number.
     320 * @param siginfo Additional information about the signal.
     321 */
     322static void _queue_signal(int signo, posix_siginfo_t *siginfo)
    293323{
    294324        assert(signo >= 0 && signo <= _TOP_SIGNAL);
    295325        assert(siginfo != NULL);
     326       
     327        signal_queue_item *item = malloc(sizeof(signal_queue_item));
     328        link_initialize(&(item->link));
     329        item->signo = signo;
     330        memcpy(&item->siginfo, siginfo, sizeof(posix_siginfo_t));
     331        list_append(&(item->link), &_signal_queue);
     332}
     333
     334
     335/**
     336 * Executes an action associated with the given signal.
     337 *
     338 * @param signo Signal number.
     339 * @param siginfo Additional information about the circumstances of this raise.
     340 * @return 0 if the action has been successfully executed. -1 if the signal is
     341 *     blocked.
     342 */
     343static int _raise_sigaction(int signo, posix_siginfo_t *siginfo)
     344{
     345        assert(signo >= 0 && signo <= _TOP_SIGNAL);
     346        assert(siginfo != NULL);
    296347
    297348        fibril_mutex_lock(&_signal_mutex);
     
    301352        if (posix_sigismember(&_signal_mask, signo) ||
    302353            action.sa_handler == SIG_HOLD) {
    303                 // TODO: queue signal
     354                _queue_signal(signo, siginfo);
    304355                fibril_mutex_unlock(&_signal_mutex);
    305356                return -1;
     
    312363        if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) {
    313364                _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER;
    314         };
     365        }
    315366
    316367        if (action.sa_flags & SA_SIGINFO) {
     
    328379
    329380/**
    330  *
    331  * @param sig
    332  * @return
     381 * Raise all unblocked previously queued signals.
     382 */
     383static void _dequeue_unblocked_signals()
     384{
     385        link_t *iterator = _signal_queue.head.next;
     386        link_t *next;
     387       
     388        while (iterator != &(_signal_queue).head) {
     389                next = iterator->next;
     390               
     391                signal_queue_item *item =
     392                    list_get_instance(iterator, signal_queue_item, link);
     393               
     394                if (!posix_sigismember(&_signal_mask, item->signo) &&
     395                    _signal_actions[item->signo].sa_handler != SIG_HOLD) {
     396                        list_remove(&(item->link));
     397                        _raise_sigaction(item->signo, &(item->siginfo));
     398                        free(item);
     399                }
     400               
     401                iterator = next;
     402        }
     403}
     404
     405/**
     406 * Raise a signal for the calling process.
     407 *
     408 * @param sig Signal number.
     409 * @return -1 with errno set on failure, 0 on success.
    333410 */
    334411int posix_raise(int sig)
     
    347424
    348425/**
    349  *
    350  * @param pid
    351  * @param signo
    352  * @return
     426 * Raises a signal for a selected process.
     427 *
     428 * @param pid PID of the process for which the signal shall be raised.
     429 * @param signo Signal to raise.
     430 * @return -1 with errno set on failure (possible errors include unsupported
     431 *     action, invalid signal number, lack of permissions, etc.), 0 on success.
    353432 */
    354433int posix_kill(posix_pid_t pid, int signo)
     
    383462
    384463/**
    385  *
    386  * @param pid
    387  * @param sig
    388  * @return
     464 * Send a signal to a process group. Always fails at the moment because of
     465 * lack of this functionality in HelenOS.
     466 *
     467 * @param pid PID of the process group.
     468 * @param sig Signal number.
     469 * @return -1 on failure, 0 on success (see kill()).
    389470 */
    390471int posix_killpg(posix_pid_t pid, int sig)
     
    395476
    396477/**
    397  *
    398  * @param pinfo
    399  * @param message
     478 * Outputs information about the signal to the standard error stream.
     479 *
     480 * @param pinfo SigInfo struct to write.
     481 * @param message String to output alongside human-readable signal description.
    400482 */
    401483void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message)
     
    407489
    408490/**
    409  *
    410  * @param signum
    411  * @param message
     491 * Outputs information about the signal to the standard error stream.
     492 *
     493 * @param signum Signal number.
     494 * @param message String to output alongside human-readable signal description.
    412495 */
    413496void posix_psignal(int signum, const char *message)
     
    422505
    423506/**
    424  *
    425  * @param how
    426  * @param set
    427  * @param oset
    428  * @return
     507 * Manipulate the signal mask of the calling thread.
     508 *
     509 * @param how What to do with the mask.
     510 * @param set Signal set to work with.
     511 * @param oset If not NULL, the original signal mask is coppied here.
     512 * @return 0 success, errorcode on failure.
    429513 */
    430514int posix_thread_sigmask(int how, const posix_sigset_t *restrict set,
     
    452536                }
    453537        }
    454 
    455         // TODO: queued signal handling
     538       
     539        _dequeue_unblocked_signals();
    456540
    457541        fibril_mutex_unlock(&_signal_mutex);
     
    461545
    462546/**
    463  *
    464  * @param how
    465  * @param set
    466  * @param oset
    467  * @return
     547 * Manipulate the signal mask of the process.
     548 *
     549 * @param how What to do with the mask.
     550 * @param set Signal set to work with.
     551 * @param oset If not NULL, the original signal mask is coppied here.
     552 * @return 0 on success, -1 with errno set on failure.
    468553 */
    469554int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
Note: See TracChangeset for help on using the changeset viewer.