[pgpool-hackers: 3901] Re: sigusr1_interrupt_processor() does not process all pending requests

Tatsuo Ishii ishii at sraoss.co.jp
Thu May 20 17:08:52 JST 2021


> Looking into the code of sigusr1_interrupt_processor(), it seems
> sigusr1_interrupt_processor() is assumed that it processes all the
> request details in sigalFlags array even if there are multiple details
> in the array. But actually it's not.

I confirmed that sigusr1_interrupt_processor() can handle multiple
requests. That's good. However there are race condition which could
cause this:

> t-ishii$ grep signalFlags pgpool[0-2]/log/pgpool.log
> pgpool1/log/pgpool.log:2021-05-18 15:25:58: main pid 12696: LOG:  signalFlags: 3 is true
> pgpool2/log/pgpool.log:2021-05-18 15:25:58: main pid 12700: LOG:  signalFlags: 3 is true
> pgpool2/log/pgpool.log:2021-05-18 15:26:04: main pid 12700: LOG:  signalFlags: 3 is true

Because while or after execution of sigusr1_interrupt_processor(),
other process can register new requests into the signalFlags array
because there is no interlocking mechanism between the signal sender
signal_user1_to_parent_with_reason() and
sigusr1_interrupt_processor().

> I don't know if this actually gives some bad effects to pgpool or not
> but I think at least we need to confirm that.

It does. In CHECK_REQUEST:

		if (sigusr1_request) \
		{ \
			sigusr1_interrupt_processor(); \
			sigusr1_request = 0; \

If other process sends SIGUSR1 while sigusr1_interrupt_processor() is
running, sigusr1_request is set to 1 by the signal handler. But after that:

			sigusr1_request = 0; \

is executed and sigusr1_interrupt_processor() will not be called until
the next signal arrives. If the next signal does not arrive or arrives
after long period, that would be a problem.

To fix it, I think the code fragment above should be changed like
this:

		if (sigusr1_request) \
		{ \
			do {\
				sigusr1_request = 0; \
				sigusr1_interrupt_processor(); \
			} while (sigusr1_request == 1); \
		} \

This way, the condition statement (sigusr1_request == 1) will catch
the arrival of the signal while sigusr1_interrupt_processor() was
running, and it will be processed next execution of
sigusr1_interrupt_processor().

Note that similar code fragment also exists in Pgpoolmain. This also
should be changed to:

		if (sigusr1_request)
		{
			do {
				sigusr1_request = 0;
				sigusr1_interrupt_processor();
			} while (sigusr1_request == 1);
		}

Also I have changed some log message level from DEBUG1 to LOG because
they are important information.

Comments are welcome.

Best regards,
--
Tatsuo Ishii
SRA OSS, Inc. Japan
English: http://www.sraoss.co.jp/index_en.php
Japanese:http://www.sraoss.co.jp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: sigusr1.diff
Type: text/x-patch
Size: 1658 bytes
Desc: not available
URL: <http://www.pgpool.net/pipermail/pgpool-hackers/attachments/20210520/f45d5efb/attachment.bin>


More information about the pgpool-hackers mailing list