I want to remove the Python SocketHandler waiting state.

Asked 2 years ago, Updated 2 years ago, 361 views

Purpose

Python performs multi-process operations and logs each process on a log server, or part of an application's internal process.
As it is part of the application's internal process, I would like to complete this log server process successfully when I close the application.

Problems

The log server process cannot be successfully terminated because the following parts of the reference code cannot be answered while waiting for socket reception:

 chunk=self.connection.recv(slen)

I think I should turn the loop with receive buffer checks like the empty method of Queue, but is there such a mechanism?

Reference

Python Document Logging Cookbook
Send and receive logging events across the network

Reference Code

Keep the receiving end source code in the Logging Cookbook.

import pickle
import logging
import logging.handlers
import socketserver
import structure


classLogRecordStreamHandler(socketserver.StreamRequestHandler):
    """Handler for a streaming logging request."

    This basic logs the record using whatver logging policy is
    configured locally.
    """

    default(self):
        """
        Handle multiple requests-each expected to be a 4-byte length,
        followed by the LogRecord in pickle format. Logs the record
        recording to whatver policy is configured locally.
        """
        while True:
            chunk=self.connection.recv(4)
            iflen(chunk)<4:
                break
            slen=structure.unpack('>L', chunk) [0]
            chunk=self.connection.recv(slen)
            whilelen(chunk)<slen:
                chunk=chunk+self.connection.recv(slen-len(chunk))
            obj=self.unPickle(chunk)
            record=logging.makeLogRecord(obj)
            self.handleLogRecord(record)

    defunPickle (self, data):
        return pickle.loads(data)

    defaultLogRecord (self, record):
        # if a name is specified, we use the named logger than the one
        # implied by the record.
        if self.server.logname is not None:
            name = self.server.logname
        else:
            name=record.name
        logger=logging.getLogger(name)
        # N.B.EVERY record gets logged.This is because Logger.handle
        # is normally called AFTER logger-level filtering. If you want
        # to do filtering, do it at the client end to save washing
        # cycles and network bandwidth!
        logger.handle(record)

classLogRecordSocketReceiver(socketserver.ThreadingTCPServer):
    """
    Simple TCP socket-based logging receiver suite for testing.
    """

    allow_reuse_address = True

    def__init__(self, host='localhost',
                 port = logging.handlers.DEFAULT_TCP_LOGGING_PORT,
                 handler=LogRecordStreamHandler):
        socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
        self.abort = 0
        self.timeout = 1
        self.logname = None

    defserve_until_stopped(self):
        import select
        abort = 0
        while not abort:
            rd,wr,ex = select.select([self.socket.fileno(),
                                       [], [],
                                       self.timeout)
            if rd:
                self.handle_request()
            abort = self.abort

defmain():
    logging.basicConfig(
        format='%(relativeCreated)5d%(name)-15s%(levelname)-8s%(message)s')
    tcpserver=LogRecordSocketReceiver()
    print('About to start TCP server...')
    tcpserver.serve_until_stopped()

if__name__=='__main__':
    main()

python3 logging

2022-09-30 21:55

1 Answers

As I mentioned in the comment, is the waiting list for socket reception chunk=self.connection.recv(slen)?
Are you actually waiting in the rd,wr,ex=select.select([self.socket.fileno(),... section?

If so, for example, could you register a signal handler and send a signal from the main process to end the process?

classLogRecordSocketReceiver(socketserver.ThreadingTCPServer): has a message processing looped defserve_until_stopped(self): while not absolute: loop continuity conditions and finally abort=selfode.

If you add the def_init__(... to register the signal handler at the end of def_init__(... and set the self.abort flag in the signal handler, and send a signal from the main process, the log server process should end normally.

def__init__(self, host='localhost',
             port = logging.handlers.DEFAULT_TCP_LOGGING_PORT,
             handler=LogRecordStreamHandler):
    socketserver.ThreadingTCPServer.__init__(self, (host, port), handler)
    self.abort = 0
    self.timeout = 1
    self.logname = None
    signal.signal(signal.SIGINT,self.signal_handler)####Signal handler registration

def signal_handler(self, signum, stack):####Signal handler
    self.abort=1###abort flag setting

defserve_until_stopped(self):
    import select
    abort = 0
    while not abort:
        rd,wr,ex = select.select([self.socket.fileno(),
                                   [], [],
                                   self.timeout)
        if rd:
            self.handle_request()
        abort = self.abort

However, it seems that there are many operating conditions and restrictions in the Windows environment.
signal.signal(signalnum, handler)
Does this not concern the operating system?

If the thread is enabled, this function can only be run from the main thread.If you try to run this function from any other thread, a ValueError exception occurs.

This is a reminder for Windows

On Windows, signal() can only be called with SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, or SIBREAK.A ValueError will be raised in any other case. Note that not all systems defined the same set of signal names; an AttributeError will be made as a sign is not required.

On Windows, signal() can only be invoked on SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM, or SIGBREAK. Otherwise, a ValueError will occur. Note that not all systems define the same set of signal names. AttributeError occurs if the signal name is not defined as a SIG* module level constant.

This article, too.
Not receiving Python signals in a Windows environment
See @sayuri's answer


2022-09-30 21:55

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.