SChernykh / p2pool

Decentralized pool for Monero mining
GNU General Public License v3.0
1.07k stars 128 forks source link

Console does not support named pipes #237

Closed twlee79 closed 1 year ago

twlee79 commented 1 year ago

Summary: p2pool requires stdin to be TTY in order for console commands to be received. This prevents use of named pipes in a service/socket configuration as a Linux service.

Background: One potential way of using p2pool as a service in Linux systems is through a service/socket-style config, where the the service has the following configuration options:

[Service]
StandardInput=socket
Sockets=p2pool.socket

And there is a corresponding p2pool.socket providing a file to write commands to:

[Socket]
ListenFIFO=/tmp/p2pool.stdin

Commands can then be issued by writing to the file (e.g. echo "status" > /tmp/p2pool.stdin), and output can be monitored in the log or systemd journal. There are some references to this configuration in various places dating back ~1 year ago.

This configuration no longer works. p2pool will not use the socket as stdin, producing the following lines in the log:

2023-03-07 03:01:11.3473 ConsoleCommands tty is not available
2023-03-07 03:01:11.3508 P2Pool Couldn't start console commands handler

Writing to the socket produces no response from p2pool.

Preferred behaviour: p2pool should allow the use of a socket as stdin, so the service/socket configuration can be implemented.

Diagnosis: This issue is due to the following implementation details of the ConsoleCommands object (in console_commands.cpp):

    if (uv_guess_handle(0) != UV_TTY) {
        LOGERR(1, "tty is not available");
        throw std::exception();
    }
    ...
    err = uv_tty_init(&m_loop, &m_tty, 0, 1);

The console will only be created if the stdin handle type is UV_TTY. When a socket is used, the stdin handle type is UV_NAMED_PIPE instead. This handling of the console was implemented in commit dcb822f.

I have prepared a fix to address this issue and will submit a pull request.

SnAFKe commented 1 year ago

Sorry to open this issue, It doesn't have to do with the issue but have relation to this.

twlee79 Can you share your p2pool.service and p2pool.socket because i'm unable to work it correctly because give me a flood of this error "WARNING 2023-04-18 17:04:18.2393 ConsoleCommands Unknown command 2023-04-18 17:04:15.5561 P2Pool v3.2 (built with GCC/9.4.0 on Mar 31 2023)" when start the service.

SChernykh commented 1 year ago

@twlee79 Can you provide the full correct service and socket configuration files to test it? I can't make it work.

twlee79 commented 1 year ago

Here is a working configuration: p2pool.socket

# FIFO socket for controlling p2pool daemon
[Unit]
Description=Command FIFO for p2pool daemon

[Socket]
ListenFIFO=/run/p2pool/p2pool.control
DirectoryMode=0755
SocketMode=0666
SocketUser=p2pool
SocketGroup=p2pool
RemoveOnStop=true

p2pool.service

[Unit]
Description=p2pool daemon
After=network-online.target systemd-modules-load.service monerod.service
Wants=network-online.target systemd-modules-load.service monerod.service
Requires=p2pool.socket

[Service]
Type=exec
Sockets=p2pool.socket
StandardInput=socket
StandardOutput=journal
StandardError=journal
ExecStart=/usr/local/bin/p2pool.sh

ExecStop=/usr/local/bin/p2pool_stop.sh
TimeoutStopSec=60

# Run as p2pool:p2pool
User=p2pool
Group=p2pool

WorkingDirectory=/var/lib/p2pool

[Install]
WantedBy=multi-user.target

/usr/local/bin/p2pool.sh simply invokes the p2pool executable with my chosen command-line options.

/usr/local/bin/p2pool_stop.sh writes exit to the named pipe then waits for the process to terminate:


#!/bin/bash
#
# Script to exit p2pool
# Used by p2pool.service

# Issue exit command and then wait for process exit, or script timeout
echo "exit" > /run/p2pool/p2pool.control
while kill -0 "${MAINPID}" 2> /dev/null; do
  sleep 1s
done

Tested and working with build from 5f18eed and the v3.2 binaries, using a named pipe on Arch Linux, with the console control by writing to the named pipe (e.g. echo status to get status written to log). The named pipe file /run/p2pool/p2pool.control should not already exist, the socket creates and destroys this.