Skip to content

[Bug] Incorrect cpuset role assignment in getCpuSetByRole() #1862

Description

@nix-oss

Apache Cloudberry version

2.1.0-incubating

What happened

Location: src/backend/commands/resgroupcmds.c
Function getCpuSetByRole()
Lines: 1618–1649.

The getCpuSetByRole() function in src/backend/commands/resgroupcmds.c was returning cpuset values for the wrong roles.

 * Seperate cpuset by coordinator and segment
 * Return as splitcpuset
 *
 * ex:
 * cpuset = "1;4"
 * then we should assign '1' to corrdinator and '4' to segment
 * 
 * cpuset = "1"
 * assign '1' to both coordinator and segment
 */
extern char *
getCpuSetByRole(const char *cpuset)
{
	char *splitcpuset = NULL;

	if (cpuset == NULL)
	{
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				errmsg("Unexpected cpuset invalid in getCpuSetByRole")));
	}

	char *first = strchr(cpuset, ';');
	if (first == NULL)
		splitcpuset = (char *)cpuset;
	else
	{
		char *scpu = first + 1;

		/* Get result cpuset by IS_QUERY_DISPATCHER(), on master or segment */
		if (IS_QUERY_DISPATCHER())
			splitcpuset = scpu;
		else
		{
			char *mcpu = (char *)palloc0(sizeof(char) * MaxCpuSetLength);
			strncpy(mcpu, cpuset, first - cpuset);
			splitcpuset = mcpu;
		}
	}

	return splitcpuset;
}

This bug manifests in heterogeneous Cloudberry clusters where the coordinator and segment nodes have different numbers of CPU cores.
The issue becomes visible only when the core counts differ; on homogeneous clusters the swapped values would be identical and the bug would go unnoticed.

When the function receives a cpuset string formatted as "coordinator_cpus;segment_cpus" (e.g., "0-7;0-15" where coordinator has 8 cores and segments have 16 cores), it should return:

  • coordinator cpuset (first part) when called from the coordinator (dispatcher),
  • segment cpuset (second part) when called from segments.

However, the logic was inverted – it returned the opposite value for each role, causing incorrect CPU affinity assignment.

What you think should happen instead

Currently, the assignments are inverted. The fix is to swap the logic so that the coordinator gets mcpu and the segment gets scpu:

 * Seperate cpuset by coordinator and segment
 * Return as splitcpuset
 *
 * ex:
 * cpuset = "1;4"
 * then we should assign '1' to corrdinator and '4' to segment
 * 
 * cpuset = "1"
 * assign '1' to both coordinator and segment
 */
extern char *
getCpuSetByRole(const char *cpuset)
{
	char *splitcpuset = NULL;

	if (cpuset == NULL)
	{
		ereport(ERROR,
				(errcode(ERRCODE_SYNTAX_ERROR),
				errmsg("Unexpected cpuset invalid in getCpuSetByRole")));
	}

	char *first = strchr(cpuset, ';');
	if (first == NULL)
		splitcpuset = (char *)cpuset;
	else
	{
		char *scpu = first + 1;

		/* Get result cpuset by IS_QUERY_DISPATCHER(), on master or segment */
		if (IS_QUERY_DISPATCHER())
		{
			char *mcpu = (char *)palloc0(sizeof(char) * MaxCpuSetLength);
			strncpy(mcpu, cpuset, first - cpuset);
			splitcpuset = mcpu;
		}
		else
            splitcpuset = scpu;
	}

	return splitcpuset;
}

How to reproduce

Prerequisites:
A heterogeneous Cloudberry cluster with:

  • 1 coordinator node – 8 vCPUs (cores 0–7)
  • 2 segment nodes – 18 vCPUs each (cores 0–17)

Steps:

  1. Connect to the coordinator node via psql.
  2. Create a resource group (or alter an existing one) with a cpuset that includes both coordinator and segment CPU ranges, separated by a semicolon: ALTER RESOURCE GROUP rgroup1 SET CPUSET '4-7;9-17';
  3. The command will fail with an error similar to: cpu cores %s are unavailable on the system

I'm currently trying to fix it and rebuilding the code locally to verify the changes.

I hope the details I've provided above (root cause, reproduction steps, and proposed fix) will be helpful

Operating System

Ubuntu 22.04

Anything else

No response

Are you willing to submit PR?

  • Yes, I am willing to submit a PR!

Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    type: BugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions