Skip to content

Menu

  • Welcome
  • Blog
  • 云计算
    • Docker
    • kubernetes
    • vSphere
  • 大数据
    • Elasticsearch
    • Flink
    • Hadoop
  • 数据分析
  • Linux
  • “Hello world”
    • Bash
    • Golang
    • Python
    • Scala
  • Web
    • Frontend
    • Backend
  • Network
  • AI
  • Wheels

归档

  • 2025 年 2 月
  • 2024 年 8 月
  • 2019 年 8 月

Calendar

2024 年 8 月
一 二 三 四 五 六 日
 1234
567891011
12131415161718
19202122232425
262728293031  
« 8 月   2 月 »

分类

  • linux
  • signal
  • 未分类

Copyright Yaochenzhi's Blog 2025 | Theme by ThemeinProgress | Proudly powered by WordPress

Yaochenzhi's Blog
  • Welcome
  • Blog
  • 云计算
    • Docker
    • kubernetes
    • vSphere
  • 大数据
    • Elasticsearch
    • Flink
    • Hadoop
  • 数据分析
  • Linux
  • “Hello world”
    • Bash
    • Golang
    • Python
    • Scala
  • Web
    • Frontend
    • Backend
  • Network
  • AI
  • Wheels
Written by yaochenzhi2024年8月23日

Linux signal信号处理机制与信号掩码

linux . signal Article

问题现象:

服务配置变更,下发节点通过signal触发本地缓存更新时。日志显示信号正常接收,执行缓存更新入口函数,但无缓存更新成功结日志。本地缓存实际未更新,无异常日志。首次更新失败后,后续均更新失败。

问题分析:

  1. 分析代码:缓存更新过程,主要流程为配置读取、解密、缓存写入,在缓存写入过程中会使用文件锁。如果存在文件锁未释放,合理解释后续均更新失败(后续无法拿到文件锁,导致失败),合理解释更新失败无异常日志(含首次)。
  2. 分析进程:查看问题进程/proc/PID/stack 信息,发现flock
  3. 分析文件:通过查看缓存更新过程中的锁文件的文件句柄打开情况和锁定测试,找出具体未被释放的锁文件。参考命令: lsof lock.file和flock lock.file -c ‘echo ok’。
  4. 分析原因:通过lsof lock.file已经确定,仅问题进程占用该文件,排除其他进程影响。针对文件锁,考虑是否存在并发影响,查看日志,发现前后2秒钟内,下发两次变更,两次signal,很有可能第一次执行过程中,文件锁未释放,触发第二次执行。
  5. 构造验证:使用如下代码验证,符合预期。

问题根因:

第一次signal处理过程中,获取到文件锁后,未释放文件锁前,接收到第二次signal,第一次handle代码直接结束,文件锁被当前进程占用后未释放,导致第二次也无法获取文件锁

Linux signal信号处理机制与信号掩码:

信号掩码(Signal Mask):在信号处理中,掩码用于控制进程是否接收某些信号。信号掩码实际上“掩盖”了信号,即在某些情况下阻止信号的传递,直到掩码被更改或解除。

参考:pthread_sigmask() — Examine or change a thread blocked signals format – IBM Documentation

#!/bin/env python3
import os
import time
import fcntl
import signal
import argparse


SIGNAL = signal.SIGUSR1

SIGNAL_BLOCKING = False


# Define signal block
def signal_block(func):

    def _inner(*args, **kwargs):
        if not SIGNAL_BLOCKING:
            print(f"Non signal blocking function handling")
            return func(*args, **kwargs)

        # Block SIGUSR1 while handling the signal
        print(f"Signal blocking function handling")
        old_mask = signal.pthread_sigmask(signal.SIG_BLOCK, {SIGNAL})
        try:
            func(*args, **kwargs)
        finally:
            # Restore the old signal mask
            signal.pthread_sigmask(signal.SIG_SETMASK, old_mask)
    return _inner


# Define the signal handler
@signal_block
def signal_handler(signum, frame):
    print(f"Signal {signum} received.")
    lock_file_hello()


# Set up the signal handling
def setup_signal_handling():
    signal.signal(SIGNAL, signal_handler)


def lock_file_hello(file_path='hello.lock'):
    with open(file_path, 'a') as file:
        try:
            # Acquire an exclusive lock
            fcntl.flock(file, fcntl.LOCK_EX)
            print(f"Locked {file_path} ")

            print(f"Work start ")

            # Simulate work
            time.sleep(10)

            print(f"Work done")

        finally:
            # Release the lock
            fcntl.flock(file, fcntl.LOCK_UN)
            print(f"Unlocked {file_path}")


# Parse signal blocking option
def parse_option():
    global SIGNAL_BLOCKING

    parser = argparse.ArgumentParser(description="Example script with blocks of options")

    parser.add_argument('--block', action='store_true', help='Enable signal blocking')

    args = parser.parse_args()

    SIGNAL_BLOCKING = args.block


# Main function to run the program
def main():
    parse_option()
    setup_signal_handling()
    print(f"Waiting for a signal, sending using 'kill -s {SIGNAL} {os.getpid()}'")
    while True:
        time.sleep(10)


if __name__ == "__main__":
    main()

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

归档

  • 2025 年 2 月
  • 2024 年 8 月
  • 2019 年 8 月

Calendar

2024 年 8 月
一 二 三 四 五 六 日
 1234
567891011
12131415161718
19202122232425
262728293031  
« 8 月   2 月 »

分类

  • linux
  • signal
  • 未分类

Copyright Yaochenzhi's Blog 2025 | Theme by ThemeinProgress | Proudly powered by WordPress