En C ++ 17, ¿no está definido para proteger los datos pasados ​​de un controlador de señales usando atomics sin bloqueo? -- ++ campo con signals campo con c++17 camp Relacionados El problema

In C++17, is it undefined to protect data passed from a signal handler using lock-free atomics?


2
vote

problema

Español

Según mi lectura de preguntas anteriores, la norma permite acceder a atómicas sin bloqueo en un controlador de señales, y cualquier modificación de los objetos "lisos" se vuelve indefinida. Si eso es así, ¿es el siguiente patrón, donde la variable atómica es una barrera de memoria para las variables no atómicas, indefinidas también?

El patrón a continuación es el de un tampón de anillo de un solo productor. La señal es el productor y un hilo es el consumidor. Por favor, ignore la ineficiencia en el hilo de recolección que está girando, no quería complicar un ejemplo ya complicado.

AFAICT, este patrón es seguro para usar en los manipuladores de señales, ya que las variables atómicas evitan las razas, y evito las asignaciones de memoria dentro del controlador de señales. Sin embargo, modifica los objetos no atómicos en un controlador de señal.

  vector<vector<int>> ring; atomic<int> push_idx; atomic<int> pop_idx;  void init() {     ring.resize(8);     for (auto &v : ring)     {         v.resize(10);     } }  int advance_idx(int i) {     return (i + 1) % 8; }  int buf[5];  void sig_handler() {     int a = push_idx.load(memory_order_relaxed);     int p = pop_idx.load(memory_order_acquire);     if (advance_idx(a) == p)     {         return; // ring overflow     }      // fill up static-linkage data     for (int i = 0; i < 5; i++)     {         buf[i] = i;     }      // copy some static-linkage data into buffer     for (int i = 0; i < 5; i++)     {         ring[a][i] = buf[i];     }     ring[a].resize(5);     push_idx.store(advance_idx(a), memory_order_release) }  void collecting_thread() {     for (;;)     {         int p = pop_idx.load(memory_order_relaxed);         int a = push_idx.load(memory_order_acquire);         if (p == a)         {             continue; // nothing to do         }          auto &vec_to_process = ring[p];         process_vec(std::move(vec_to_process); //may move-from         vec_to_process.clear();         vec_to_process.resize(10);         pop_idx.store(advance_idx(p), memory_order_release);     } }   
Original en ingles

According to my reading of past questions, the standard allows accessing lock-free atomics in a signal handler, and any modification of "plain" objects becomes undefined. If that's so, is the following pattern, where the atomic variable is a memory barrier for non-atomic variables, undefined as well?

Pattern below is that of a single-producer-signle-consumer ring buffer. The signal is the producer and a thread is the consumer. Please disregard the inefficiency in the collecting thread that's spinning - didn't want to complicate an already complicated example.

AFAICT, this pattern is safe to use in signal handlers, because the atomic variables prevent any races, and I avoid memory allocations inside the signal handler. However it does modify non-atomic objects in a signal handler.

vector<vector<int>> ring; atomic<int> push_idx; atomic<int> pop_idx;  void init() {     ring.resize(8);     for (auto &v : ring)     {         v.resize(10);     } }  int advance_idx(int i) {     return (i + 1) % 8; }  int buf[5];  void sig_handler() {     int a = push_idx.load(memory_order_relaxed);     int p = pop_idx.load(memory_order_acquire);     if (advance_idx(a) == p)     {         return; // ring overflow     }      // fill up static-linkage data     for (int i = 0; i < 5; i++)     {         buf[i] = i;     }      // copy some static-linkage data into buffer     for (int i = 0; i < 5; i++)     {         ring[a][i] = buf[i];     }     ring[a].resize(5);     push_idx.store(advance_idx(a), memory_order_release) }  void collecting_thread() {     for (;;)     {         int p = pop_idx.load(memory_order_relaxed);         int a = push_idx.load(memory_order_acquire);         if (p == a)         {             continue; // nothing to do         }          auto &vec_to_process = ring[p];         process_vec(std::move(vec_to_process); //may move-from         vec_to_process.clear();         vec_to_process.resize(10);         pop_idx.store(advance_idx(p), memory_order_release);     } } 
        
         
         

Lista de respuestas

0
 
vote

Respondiendo a mi propia pregunta basada en los comentarios: parece que es un comportamiento indefinido, ya que siempre ha sido.

Como se pone en la respuesta a SEM_post, manipuladores de señales y comportamiento indefinido < / a> (que se trata de POSIX), no está definido, no porque contradice la forma en que se trata de señales, hilos, atómicos o trabajo de CPU, sino porque especificando el comportamiento correcto es difícil sin ganancias significativas.

En la mayoría de los casos, la cosa adecuada para hacer con las señales es simplemente establecer una bandera en el controlador de señal, o "aceptar la señal" (Sigwait () et. AL). En mi caso, esto no funcionaría, ya que necesito obtener la traza de la pila (controlador SIGPROF) y entregarlo a la aplicación.

 

Answering my own question based on the comments - it seems like it's undefined behavior, as it's always been.

As put in the answer to sem_post, signal handlers, and undefined behavior (which is about POSIX), it's undefined not because it contradicts the way signals, threads, atomics, or CPUs work, but because specifying the correct behavior is difficult with no significant gains.

In most cases the proper thing to do with signals is either to just set a flag in the signal handler, or "accept the signal" (sigwait() et. al). In my case this wouldn't work as I need to get the stack trace (SIGPROF handler) and deliver it to the application.

 
 

Relacionados problema

0  Visual Studio 2019 está configurado para: C ++ 17, pero se parece más a C ++ 14  ( Visual studio 2019 is configured forc17 but it looks more like c14 ) 
Si compile algún código con lo siguiente: #include <string_view> std::string_view strv{ "Test 1" }; Obtengo este error: Error C2065 'string_view...

21  C ++ equivalente al resultado del resultado de ROX <T, E>?  ( C equivalent of rusts resultt e type ) 
Me gusta usar STD :: Experimental :: Opcional en mi código C ++, pero el problema es que Value_or requiere que el valor predeterminado sea del mismo tipo que ...

2  Cómo transferir los nodos entre dos BOOST :: intrusivo :: Objetos de Slist  ( How to transfer nodes between two boostintrusiveslist objects ) 
¿Es válido transferir los nodos entre dos objetos auto one = boost::intrusive::slist<Node, boost::intrusive::cache_last<true>>{}; auto two = boost::intrusive...

0  Toggle Pass por parámetro de referencia basado en Tipo de plantilla C ++  ( Toggle pass by reference parameter based on template type c ) 
Estoy implementando una función "Starts_with" para verificar si una cadena comienza con algún prefijo. Quiero que la función pueda comparar std::string y s...

5  ¿Cómo trabajar con los punteros en la memoria cruda proporcionada por los asignadores personalizados (sin UB)?  ( How to work with pointers into raw memory provided by custom allocators without ) 
Estoy tratando de escribir un contenedor de aloocatorios. Supongamos que quiero asignar un trozo de memoria para tres objetos: T* chunk = std::allocator_tr...

2  C ++ Bug de hilo separado  ( C detached thread bug ) 
Después de pasar un día tratando de resolver un misterioso error, busco su ayuda. Cuando ejecuto el código Bellow, ¿entiende por qué se duplica la salida co...

0  C ++ 17: el constructor definido por el usuario siempre se llama y el operador + sobrecarga no funciona para la clase infantil  ( C17 user defined constructor is always called and operator overloading not w ) 
En general, estoy implementando una clase para modularizar un número sin firmar (una envoltura para los tipos sin firmar). Quiero que mi clase cumpla con esta...

2  ¿Cómo diseñar una sola escritura y una lectura múltiple cuando el recurso protegido debe ser devuelto por Getter como un shared_ptr en C ++ moderno?  ( How to design a single write and multiple read when the protected resource need ) 
Tengo un hilo de escritor Escribe en un mapa en un objeto, y muchos objetos de lector cada uno en su propio hilo para realizar leídas solo en el mapa, mi dise...

14  ¿Debo hacer que mis variables locales const o móvil?  ( Should i make my local variables const or movable ) 
Mi comportamiento predeterminado para cualquier objeto en los ámbitos locales es hacerlo const . E.G.: auto const cake = bake_cake(arguments); Intento...

399  Cómo pasar HTML a JQERY y encontrar un solo elemento y reemplazar  ( Enum to string in modern c11 c14 c17 and future c20 ) 
Enum a cadena en moderno C ++ 11 / C ++ 14 / C ++ 17 y Future C ++ 20 0123456789012345222 Contrariamente a todas las demás preguntas similares, esta pregunt...




© 2022 respuesta.top Reservados todos los derechos. Centro de preguntas y respuestas reservados todos los derechos