Changes in uspace/lib/posix/signal.c [4419c34:f215bb5f] in mainline
- File:
-
- 1 edited
-
uspace/lib/posix/signal.c (modified) (25 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/posix/signal.c
r4419c34 rf215bb5f 45 45 #include "libc/task.h" 46 46 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 55 48 56 49 /* Used to serialize signal handling. */ 57 50 static FIBRIL_MUTEX_INITIALIZE(_signal_mutex); 58 51 59 static LIST_INITIALIZE(_signal_queue);60 61 52 static posix_sigset_t _signal_mask = 0; 62 53 … … 64 55 .sa_mask = 0, .sa_flags = 0, .sa_sigaction = NULL } 65 56 66 /* Actions associated with each signal number. */67 57 static struct posix_sigaction _signal_actions[_TOP_SIGNAL + 1] = { 68 58 DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, DEFAULT_HANDLER, … … 136 126 } 137 127 138 /** Just an empty function to get an unique pointer value for comparison.128 /** 139 129 * 140 130 * @param signo … … 145 135 } 146 136 147 /** Empty function to be used as ignoring handler.137 /** 148 138 * 149 139 * @param signo … … 154 144 } 155 145 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 160 150 */ 161 151 int posix_sigemptyset(posix_sigset_t *set) … … 167 157 } 168 158 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 173 163 */ 174 164 int posix_sigfillset(posix_sigset_t *set) … … 180 170 } 181 171 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 187 177 */ 188 178 int posix_sigaddset(posix_sigset_t *set, int signo) … … 194 184 } 195 185 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 201 191 */ 202 192 int posix_sigdelset(posix_sigset_t *set, int signo) … … 208 198 } 209 199 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 215 205 */ 216 206 int posix_sigismember(const posix_sigset_t *set, int signo) … … 221 211 } 222 212 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 /** 226 214 * 227 215 * @param sig … … 243 231 } 244 232 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 253 239 */ 254 240 int posix_sigaction(int sig, const struct posix_sigaction *restrict act, … … 266 252 " or fully unsupported signal. This handler may only be" 267 253 " invoked by the raise() function, which may not be what" 268 " the application developer intended ");254 " the application developer intended.\nSignal name"); 269 255 } 270 256 … … 276 262 } 277 263 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 283 269 */ 284 270 void (*posix_signal(int sig, void (*func)(int)))(int) … … 298 284 } 299 285 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 */ 292 static int _raise_sigaction(int signo, posix_siginfo_t *siginfo) 312 293 { 313 294 assert(signo >= 0 && signo <= _TOP_SIGNAL); 314 295 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 is329 * 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);335 296 336 297 fibril_mutex_lock(&_signal_mutex); … … 340 301 if (posix_sigismember(&_signal_mask, signo) || 341 302 action.sa_handler == SIG_HOLD) { 342 _queue_signal(signo, siginfo);303 // TODO: queue signal 343 304 fibril_mutex_unlock(&_signal_mutex); 344 305 return -1; … … 351 312 if ((action.sa_flags & SA_RESETHAND) && signo != SIGILL && signo != SIGTRAP) { 352 313 _signal_actions[signo] = (struct posix_sigaction) DEFAULT_HANDLER; 353 } 314 }; 354 315 355 316 if (action.sa_flags & SA_SIGINFO) { … … 366 327 } 367 328 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 396 333 */ 397 334 int posix_raise(int sig) … … 409 346 } 410 347 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 417 353 */ 418 354 int posix_kill(posix_pid_t pid, int signo) … … 424 360 } 425 361 426 if (signo > _TOP_SIGNAL) {427 errno = EINVAL;428 return -1;429 }430 431 362 if (pid == (posix_pid_t) task_get_id()) { 432 363 return posix_raise(signo); 364 } 365 366 if (pid > _TOP_SIGNAL) { 367 errno = EINVAL; 368 return -1; 433 369 } 434 370 … … 446 382 } 447 383 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 454 389 */ 455 390 int posix_killpg(posix_pid_t pid, int sig) … … 459 394 } 460 395 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 465 400 */ 466 401 void posix_psiginfo(const posix_siginfo_t *pinfo, const char *message) … … 471 406 } 472 407 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 477 412 */ 478 413 void posix_psignal(int signum, const char *message) … … 486 421 } 487 422 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 494 429 */ 495 430 int posix_thread_sigmask(int how, const posix_sigset_t *restrict set, … … 517 452 } 518 453 } 519 520 _dequeue_unblocked_signals();454 455 // TODO: queued signal handling 521 456 522 457 fibril_mutex_unlock(&_signal_mutex); … … 525 460 } 526 461 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 533 468 */ 534 469 int posix_sigprocmask(int how, const posix_sigset_t *restrict set,
Note:
See TracChangeset
for help on using the changeset viewer.
