public override void ReceiveLog(LogRecord record, string kind)
        {
            MemoryBuffer <byte> buf = new MemoryBuffer <byte>();

            record.WriteRecordToBuffer(this.LogInfoOptions, buf);

            MasterBuffer.NonStopWriteWithLock(buf.Memory, true, FastStreamNonStopWriteMode.DiscardExistingData);

            lock (LockObj)
            {
                foreach (var pipe in this.SubscribersList)
                {
                    pipe.CounterPart._NullCheck();

                    lock (pipe.CounterPart.StreamWriter.LockObj)
                    {
                        if (pipe.CounterPart.StreamWriter.NonStopWriteWithLock(buf.Memory, false, FastStreamNonStopWriteMode.DiscardExistingData) != 0)
                        {
                            // To avoid deadlock, CompleteWrite() must be called from other thread.
                            // (CompleteWrite() ==> Disconnect ==> Socket Log will recorded ==> ReceiveLog() ==> this function will be called!)
                            TaskUtil.StartSyncTaskAsync(() => pipe.CounterPart.StreamWriter.CompleteWrite(false), false, false)._LaissezFaire(true);
                        }
                    }
                }
            }
        }
        public TelnetStreamWatcherBase(TelnetStreamWatcherOptions options)
        {
            this.Options = options;

            Listener = TcpIp.CreateListener(new TcpListenParam(async(listener, sock) =>
            {
                try
                {
                    Con.WriteDebug($"TelnetStreamWatcher({this.ToString()}: Connected: {sock.EndPointInfo._GetObjectDump()}");

                    using (var destStream = sock.GetStream())
                    {
                        if (sock.Info.Ip.RemoteIPAddress == null || Options.IPAccessFilter(sock.Info.Ip.RemoteIPAddress) == false)
                        {
                            Con.WriteDebug($"TelnetStreamWatcher({this.ToString()}: Access denied: {sock.EndPointInfo._GetObjectDump()}");

                            await destStream.WriteAsync("You are not allowed to access to this service.\r\n\r\n"._GetBytes_Ascii());

                            await Task.Delay(100);

                            return;
                        }

                        using (var pipePoint = await SubscribeImplAsync())
                        {
                            // ソケットから Enter キー入力を待機する
                            Task keyInputTask = TaskUtil.StartAsyncTaskAsync(async() =>
                            {
                                using StreamReader lineReader = new StreamReader(destStream);

                                while (true)
                                {
                                    string?line = await lineReader.ReadLineAsync();

                                    if (line == null)
                                    {
                                        break;
                                    }

                                    line = line.Trim();

                                    if (line._IsSamei("s"))
                                    {
                                        // Socket リストの表示
                                        var list = LocalNet.GetSockList().OrderBy(x => x.Connected);

                                        StringWriter w = new StringWriter();

                                        w.WriteLine();

                                        foreach (var sock in list)
                                        {
                                            string tmp = sock._GetObjectDump();
                                            w.WriteLine(tmp);
                                        }

                                        w.WriteLine();

                                        w.WriteLine($"Total sockets: {list.Count()}");

                                        w.WriteLine();

                                        byte[] data = w.ToString()._GetBytes_Ascii();

                                        var pipe = pipePoint;
                                        if (pipe.CounterPart != null)
                                        {
                                            lock (pipe.CounterPart.StreamWriter.LockObj)
                                            {
                                                if (pipe.CounterPart.StreamWriter.NonStopWriteWithLock(data, false, FastStreamNonStopWriteMode.DiscardExistingData) != 0)
                                                {
                                                    // To avoid deadlock, CompleteWrite() must be called from other thread.
                                                    // (CompleteWrite() ==> Disconnect ==> Socket Log will recorded ==> ReceiveLog() ==> this function will be called!)
                                                    TaskUtil.StartSyncTaskAsync(() => pipe.CounterPart.StreamWriter.CompleteWrite(false), false, false)._LaissezFaire(true);
                                                }
                                            }
                                        }
                                    }
                                    else
                                    {
                                        // GC
                                        Dbg.WriteLine($"Manual GC is called by the administrator.");

                                        long start = FastTick64.Now;
                                        Dbg.GcCollect();
                                        long end = FastTick64.Now;

                                        long spentTime = end - start;

                                        Dbg.WriteLine($"Manual GC Took Time: {spentTime} msecs.");
                                    }
                                }
                            });

                            try
                            {
                                // ソケットに対して、pipePoint のストリームをそのまま非同期で流し込む
                                using (var pipeStub = pipePoint.GetNetAppProtocolStub())
                                    using (var srcStream = pipeStub.GetStream())
                                    {
                                        await srcStream.CopyToAsync(destStream, sock.GrandCancel);
                                    }
                            }
                            finally
                            {
                                await UnsubscribeImplAsync(pipePoint);

                                await pipePoint.CleanupAsync(new DisconnectedException());

                                await keyInputTask._TryAwait(noDebugMessage: true);
                            }
                        }
                    }
                }
                finally
                {
                    Con.WriteDebug($"TelnetStreamWatcher({this.ToString()}: Disconnected: {sock.EndPointInfo._GetObjectDump()}");
                }
            },
                                                               "TelnetStreamWatcher",
                                                               this.Options.EndPoints.ToArray()));

            this.AddIndirectDisposeLink(this.Listener);
        }
        public void ExecMain()
        {
            if (Once.IsFirstCall() == false)
            {
                throw new ApplicationException("StartMainLoop can be called only once.");
            }

            this.SingleInstance = new SingleInstance($"UserModeService_{this.Name}");

            try
            {
                string?         eventName   = null;
                EventWaitHandle?eventHandle = null;

                if (Env.IsUnix)
                {
                    System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += UnixSigTermHandler;
                }
                else
                {
                    eventName = @"Global\usermodesvc_" + Util.Rand(16)._GetHexString().ToLower();

                    eventHandle = new EventWaitHandle(false, EventResetMode.ManualReset, eventName);

                    TaskUtil.StartSyncTaskAsync(() =>
                    {
                        eventHandle.WaitOne();

                        Win32PipeRecvHandler();
                    }, leakCheck: false)._LaissezFaire(true);
                }

                // Start the TelnetLogWatcher
                List <IPEndPoint> telnetWatcherEpList = new List <IPEndPoint>();

                telnetWatcherEpList.Add(new IPEndPoint(IPAddress.Loopback, HiveData.ManagedData.LocalLogWatchPort));
                telnetWatcherEpList.Add(new IPEndPoint(IPAddress.IPv6Loopback, HiveData.ManagedData.LocalLogWatchPort));

                if (this.TelnetLogWatcherPort != 0)
                {
                    telnetWatcherEpList.Add(new IPEndPoint(IPAddress.Any, this.TelnetLogWatcherPort));
                    telnetWatcherEpList.Add(new IPEndPoint(IPAddress.IPv6Any, this.TelnetLogWatcherPort));
                }

                TelnetWatcher = new TelnetLocalLogWatcher(new TelnetStreamWatcherOptions((ip) => ip._GetIPAddressType().BitAny(IPAddressType.LocalUnicast | IPAddressType.Loopback), null,
                                                                                         telnetWatcherEpList.ToArray()));

                InternalStart();

                lock (HiveData.DataLock)
                {
                    HiveData.ManagedData.Pid       = Env.ProcessId;
                    HiveData.ManagedData.EventName = eventName;
                }

                HiveData.SyncWithStorage(HiveSyncFlags.SaveToFile, true);

                // Save pid
                string pidFileName = Lfs.PathParser.Combine(CoresConfig.UserModeServiceSettings.GetLocalHiveDirProc.Value(), this.Name + ".pid");
                string pidBody     = Env.ProcessId.ToString() + Env.NewLine;
                Lfs.WriteStringToFile(pidFileName, pidBody, FileFlags.AutoCreateDirectory);

                Console.WriteLine(ExecMainSignature);

                // The daemon routine is now started. Wait here until InternalStop() is called.
                StoppedEvent.Wait();
            }
            finally
            {
                this.TelnetWatcher._DisposeSafe();
                this.TelnetWatcher = null;

                this.SingleInstance._DisposeSafe();
                this.SingleInstance = null;
            }
        }