Mercurial > hg > nginx
view src/os/unix/ngx_thread_mutex.c @ 8795:278ab0ed24f2 quic
HTTP/3: generate more H3_FRAME_UNEXPECTED.
As per quic-http-34, these are the cases when this error should be generated:
If an endpoint receives a second SETTINGS frame
on the control stream, the endpoint MUST respond with a connection
error of type H3_FRAME_UNEXPECTED
SETTINGS frames MUST NOT be sent on any stream other than the control
stream. If an endpoint receives a SETTINGS frame on a different
stream, the endpoint MUST respond with a connection error of type
H3_FRAME_UNEXPECTED.
A client MUST NOT send a PUSH_PROMISE frame. A server MUST treat the
receipt of a PUSH_PROMISE frame as a connection error of type
H3_FRAME_UNEXPECTED; see Section 8.
The MAX_PUSH_ID frame is always sent on the control stream. Receipt
of a MAX_PUSH_ID frame on any other stream MUST be treated as a
connection error of type H3_FRAME_UNEXPECTED.
Receipt of an invalid sequence of frames MUST be treated as a
connection error of type H3_FRAME_UNEXPECTED; see Section 8. In
particular, a DATA frame before any HEADERS frame, or a HEADERS or
DATA frame after the trailing HEADERS frame, is considered invalid.
A CANCEL_PUSH frame is sent on the control stream. Receiving a
CANCEL_PUSH frame on a stream other than the control stream MUST be
treated as a connection error of type H3_FRAME_UNEXPECTED.
The GOAWAY frame is always sent on the control stream.
author | Roman Arutyunyan <arut@nginx.com> |
---|---|
date | Fri, 11 Jun 2021 12:11:08 +0300 |
parents | 022ea0d17177 |
children |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev * Copyright (C) Nginx, Inc. */ #include <ngx_config.h> #include <ngx_core.h> /* * All modern pthread mutex implementations try to acquire a lock * atomically in userland before going to sleep in kernel. Some * spins before the sleeping. * * In Solaris since version 8 all mutex types spin before sleeping. * The default spin count is 1000. It can be overridden using * _THREAD_ADAPTIVE_SPIN=100 environment variable. * * In MacOSX all mutex types spin to acquire a lock protecting a mutex's * internals. If the mutex is busy, thread calls Mach semaphore_wait(). * * * PTHREAD_MUTEX_NORMAL lacks deadlock detection and is the fastest * mutex type. * * Linux: No spinning. The internal name PTHREAD_MUTEX_TIMED_NP * remains from the times when pthread_mutex_timedlock() was * non-standard extension. Alias name: PTHREAD_MUTEX_FAST_NP. * FreeBSD: No spinning. * * * PTHREAD_MUTEX_ERRORCHECK is usually as fast as PTHREAD_MUTEX_NORMAL * yet has lightweight deadlock detection. * * Linux: No spinning. The internal name: PTHREAD_MUTEX_ERRORCHECK_NP. * FreeBSD: No spinning. * * * PTHREAD_MUTEX_RECURSIVE allows recursive locking. * * Linux: No spinning. The internal name: PTHREAD_MUTEX_RECURSIVE_NP. * FreeBSD: No spinning. * * * PTHREAD_MUTEX_ADAPTIVE_NP spins on SMP systems before sleeping. * * Linux: No deadlock detection. Dynamically changes a spin count * for each mutex from 10 to 100 based on spin count taken * previously. * FreeBSD: Deadlock detection. The default spin count is 2000. * It can be overridden using LIBPTHREAD_SPINLOOPS environment * variable or by pthread_mutex_setspinloops_np(). If a lock * is still busy, sched_yield() can be called on both UP and * SMP systems. The default yield loop count is zero, but * it can be set by LIBPTHREAD_YIELDLOOPS environment * variable or by pthread_mutex_setyieldloops_np(). * Solaris: No PTHREAD_MUTEX_ADAPTIVE_NP. * MacOSX: No PTHREAD_MUTEX_ADAPTIVE_NP. * * * PTHREAD_MUTEX_ELISION_NP is a Linux extension to elide locks using * Intel Restricted Transactional Memory. It is the most suitable for * rwlock pattern access because it allows simultaneous reads without lock. * Supported since glibc 2.18. * * * PTHREAD_MUTEX_DEFAULT is default mutex type. * * Linux: PTHREAD_MUTEX_NORMAL. * FreeBSD: PTHREAD_MUTEX_ERRORCHECK. * Solaris: PTHREAD_MUTEX_NORMAL. * MacOSX: PTHREAD_MUTEX_NORMAL. */ ngx_int_t ngx_thread_mutex_create(ngx_thread_mutex_t *mtx, ngx_log_t *log) { ngx_err_t err; pthread_mutexattr_t attr; err = pthread_mutexattr_init(&attr); if (err != 0) { ngx_log_error(NGX_LOG_EMERG, log, err, "pthread_mutexattr_init() failed"); return NGX_ERROR; } err = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK); if (err != 0) { ngx_log_error(NGX_LOG_EMERG, log, err, "pthread_mutexattr_settype" "(PTHREAD_MUTEX_ERRORCHECK) failed"); return NGX_ERROR; } err = pthread_mutex_init(mtx, &attr); if (err != 0) { ngx_log_error(NGX_LOG_EMERG, log, err, "pthread_mutex_init() failed"); return NGX_ERROR; } err = pthread_mutexattr_destroy(&attr); if (err != 0) { ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_mutexattr_destroy() failed"); } return NGX_OK; } ngx_int_t ngx_thread_mutex_destroy(ngx_thread_mutex_t *mtx, ngx_log_t *log) { ngx_err_t err; err = pthread_mutex_destroy(mtx); if (err != 0) { ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_mutex_destroy() failed"); return NGX_ERROR; } return NGX_OK; } ngx_int_t ngx_thread_mutex_lock(ngx_thread_mutex_t *mtx, ngx_log_t *log) { ngx_err_t err; err = pthread_mutex_lock(mtx); if (err == 0) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_mutex_lock() failed"); return NGX_ERROR; } ngx_int_t ngx_thread_mutex_unlock(ngx_thread_mutex_t *mtx, ngx_log_t *log) { ngx_err_t err; err = pthread_mutex_unlock(mtx); #if 0 ngx_time_update(); #endif if (err == 0) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, log, err, "pthread_mutex_unlock() failed"); return NGX_ERROR; }