Changeset 4419c34 in mainline
- Timestamp:
- 2011-08-17T17:44:07Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 0d33863
- Parents:
- 4c8f5e7
- Location:
- uspace/lib/posix
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/signal.c
r4c8f5e7 r4419c34 45 45 #include "libc/task.h" 46 46 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 */ 48 55 49 56 /* Used to serialize signal handling. */ 50 57 static FIBRIL_MUTEX_INITIALIZE(_signal_mutex); 51 58 59 static LIST_INITIALIZE(_signal_queue); 60 52 61 static posix_sigset_t _signal_mask = 0; 53 62 … … 55 64 .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL } 56 65 66 /* Actions associated with each signal number. */ 57 67 static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = { 58 68 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, … … 126 136 } 127 137 128 /** 138 /** Just an empty function to get an unique pointer value for comparison. 129 139 * 130 140 * @param signo … … 135 145 } 136 146 137 /** 147 /** Empty function to be used as ignoring handler. 138 148 * 139 149 * @param signo … … 144 154 } 145 155 146 /** 147 * 148 * @param set 149 * @return 156 /** Clear the signal set. 157 * 158 * @param set Pointer to the signal set. 159 * @return Always returns zero. 150 160 */ 151 161 int posix_sigemptyset(posix_sigset_t *set) … … 157 167 } 158 168 159 /** 160 * 161 * @param set 162 * @return 169 /** Fill the signal set (i.e. add all signals). 170 * 171 * @param set Pointer to the signal set. 172 * @return Always returns zero. 163 173 */ 164 174 int posix_sigfillset(posix_sigset_t *set) … … 170 180 } 171 181 172 /** 173 * 174 * @param set 175 * @param signo 176 * @return 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. 177 187 */ 178 188 int posix_sigaddset(posix_sigset_t *set, int signo) … … 184 194 } 185 195 186 /** 187 * 188 * @param set 189 * @param signo 190 * @return 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. 191 201 */ 192 202 int posix_sigdelset(posix_sigset_t *set, int signo) … … 198 208 } 199 209 200 /** 201 * 202 * @param set 203 * @param signo 204 * @return 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. 205 215 */ 206 216 int posix_sigismember(const posix_sigset_t *set, int signo) … … 211 221 } 212 222 213 /** 223 /** Unsafe variant of the sigaction() function. 224 * Doesn't do any checking of its arguments and 225 * does not deal with thread-safety. 214 226 * 215 227 * @param sig … … 231 243 } 232 244 233 /** 234 * 235 * @param sig 236 * @param act 237 * @param oact 238 * @return 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. 239 253 */ 240 254 int posix_sigaction(int sig, const struct posix_sigaction *restrict act, … … 262 276 } 263 277 264 /** 265 * 266 * @param sig 267 * @param func 268 * @return 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. 269 283 */ 270 284 void (*posix_signal(int sig, void (*func)(int)))(int) … … 284 298 } 285 299 286 /** 287 * 288 * @param signo 289 * @param siginfo 290 * @return 291 */ 292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 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) 293 312 { 294 313 assert(signo >= 0 && signo <= _TOP_SIGNAL); 295 314 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); 296 335 297 336 fibril_mutex_lock(&_signal_mutex); … … 301 340 if (posix_sigismember(&_signal_mask, signo) || 302 341 action.sa_handler == SIG_HOLD) { 303 // TODO: queue signal342 _queue_signal(signo, siginfo); 304 343 fibril_mutex_unlock(&_signal_mutex); 305 344 return -1; … … 327 366 } 328 367 329 /** 330 * 331 * @param sig 332 * @return 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. 333 396 */ 334 397 int posix_raise(int sig) … … 346 409 } 347 410 348 /** 349 * 350 * @param pid 351 * @param signo 352 * @return 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. 353 417 */ 354 418 int posix_kill(posix_pid_t pid, int signo) … … 382 446 } 383 447 384 /** 385 * 386 * @param pid 387 * @param sig 388 * @return 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()). 389 454 */ 390 455 int posix_killpg(posix_pid_t pid, int sig) … … 394 459 } 395 460 396 /** 397 * 398 * @param pinfo 399 * @param message 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. 400 465 */ 401 466 void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message) … … 406 471 } 407 472 408 /** 409 * 410 * @param signum 411 * @param message 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. 412 477 */ 413 478 void posix_psignal(int signum, const char *message) … … 421 486 } 422 487 423 /** 424 * 425 * @param how 426 * @param set 427 * @param oset 428 * @return 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. 429 494 */ 430 495 int posix_thread_sigmask(int how, const posix_sigset_t *restrict set, … … 452 517 } 453 518 } 454 455 // TODO: queued signal handling519 520 _dequeue_unblocked_signals(); 456 521 457 522 fibril_mutex_unlock(&_signal_mutex); … … 460 525 } 461 526 462 /** 463 * 464 * @param how 465 * @param set 466 * @param oset 467 * @return 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. 468 533 */ 469 534 int posix_sigprocmask(int how, const posix_sigset_t *restrict set, -
uspace/lib/posix/signal.h
r4c8f5e7 r4419c34 36 36 #define POSIX_SIGNAL_H_ 37 37 38 // TODO: documentation39 40 38 #include "libc/errno.h" 41 39 #include "sys/types.h" … … 57 55 typedef uint32_t posix_sigset_t; 58 56 typedef struct posix_mcontext { 59 / / FIXME: should not be empty to avoid compiler warnings (-pedantic)57 /* must not be empty to avoid compiler warnings (-pedantic) */ 60 58 int dummy; 61 59 } posix_mcontext_t;
Note:
See TracChangeset
for help on using the changeset viewer.