Group database:

int getgrgid_r (gid_t gid, struct group *grp, char *buffer,

size_t bufsize, struct group **result);

int getgrnam_r (

const char *name, struct group *grp,

char *buffer, size_t bufsize,

struct group **result);

User database:

int getpwuid_r (

uid_t uid, struct passwd *pwd, char *buffer,

size_t bufsize, struct passwd **result); int getpwnam_r (

const char *name, struct passwd *pwd,

char *buffer, size_t bufsize,

struct passwd **result);

These functions store a copy of the group or user record (grp or pwd, respectively) for the specified group or user (gid, uid, or name) in a buffer designated by

the arguments buffer and bufsize. The function return value is in each case either 0 for success, or an error number (such as ERANGE when the buffer is too small) to designate an error. If the requested record is not present in the group or passwd database, the functions may return success but store the value NULL into the result pointer. If the record is found and the buffer is large enough, result becomes a pointer to the struct group or struct passwd record within buffer.

The maximum required size for buffer can be determined by calling sysconf with the argument _SC_GETGR_R_SIZE_MAX (for group data) or with the argument _SC_GETPW_R_SIZE MAX(for user data).

6.6 Signals

Beware the Jabberwock, my son!

The jaws that bite, the claws that catch!

Beware the Jubjub bird, and shun

The frumious Bandersnatch!

Lewis Carroll, Through the Looking-Glass

The history of the Pthreads signal-handling model is the most convoluted and confusing part of the standard. There were several different viewpoints, and it was difficult to devise a compromise that would satisfy everyone in the working group (much less the larger and more diverse balloting group). This isn't surprising, since signals are complicated anyway, and have a widely divergent history in the industry.

There were two primary conflicting goals:

• First, 'signals should be completely compatible with traditional UNIX.' That means signal handlers and masks should remain associated with the process. That makes them virtually useless with multiple threads, which is as it should be since signals have complicating semantics that make it difficult for signals and threads to coexist peacefully. Tasks should be accomplished synchronously using threads rather than asynchronously using signals.

• Second, 'signals should be completely compatible with traditional UNIX.' This time, 'compatible' means signal handlers and masks should be completely thread-private. Most existing UNIX code would then function essentially the same running within a thread as it had within a process. Code migration would be simplified.

The problem is that the definitions of 'compatible' were incompatible. Although many people involved in the negotiation may not agree with the final result, nearly everyone would agree that those who devised the compromise did an extraordinarily good job, and that they were quite courageous to attempt the feat.

When writing threaded code,treat signals as Jabberwocks— curious and potentially dangerous creatures to be approached with caution,if at all.

It is always best to avoid using signals in conjunction with threads. At the same time, it is often not possible or practical to keep them separate. When signals and threads meet, beware. If at all possible, use only pthread_sigmask to mask signals in the main thread, and sigwait to handle signals synchronously within a single thread dedicated to that purpose. If you must use sigaction (or equivalent) to handle synchronous signals (such as SIGSEGV) within threads, be especially cautious. Do as little work as possible within the signal-catching function.

All signal actions are process-wide. A program must coordinate any use of sigaction between threads. This is nonmodular, but also relatively simple, and signals have never been modular. A function that dynamically modifies signal actions, for example, to catch or ignore SIGFPE while it performs floating-point operations, or SIGPIPE while it performs network I/O, will be tricky to code on a threaded system.

While modifying the process signal action for a signal number is itself thread-safe, there is no protection against some other thread setting a new signal action immediately afterward. Even if the code tries to be 'good' by saving the original signal action and restoring it, it may be foiled by another thread, as shown in Figure 6.1.

Signals that are not 'tied' to a specific hardware execution context are delivered to one arbitrary thread within the process. That means a SIGCHLD raised by a child process termination, for example, may not be delivered to the thread that created the child. Similarly, a call to kill results in a signal that may be delivered to any thread.

6.6.1 Signal actions

Thread 1 Thread 2 Comments
sigaction(SIGFPE) Thread 1's signal action active.
sigaction(SIGFPE) Thread 2's signal action active.
Generate SIGFPE Thread 1 signal is handled by the thread 2 signal action (but still in the context of thread 1).
Restore action Thread 1 restores original signal action
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату