Skip to content

Add producer-consumer example - #167

Open
harshitaleela wants to merge 2 commits into
mainfrom
livelock
Open

Add producer-consumer example#167
harshitaleela wants to merge 2 commits into
mainfrom
livelock

Conversation

@harshitaleela

@harshitaleela harshitaleela commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added a producer-consumer example demonstrating buffered work processing with multiple producer and consumer threads.
    • Added build and debugging commands for compiling, running, inspecting, and packaging the example.
    • Added a partial semaphore implementation and troubleshooting guidance for investigating blocking behavior.
  • Documentation

    • Updated command-line help for the maximum live-lock cycle limit, including the new -lc<num> option format.

@harshitaleela
harshitaleela requested review from aayushi363 and gc00 July 19, 2026 20:42
@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates the livelock-cycle CLI option and adds a producer-consumer example with custom semaphore synchronization, a circular buffer harness, build tooling, and debugging instructions.

Changes

CLI option update

Layer / File(s) Summary
Livelock limit option parsing and help
src/launch.c
The launcher accepts the embedded -lc<num> form and documents it in the usage output.

Producer-consumer example

Layer / File(s) Summary
Semaphore implementation and blocking behavior
test/producer-consumer/partial-solution.c, test/producer-consumer/000-README
Defines semaphore initialization, posting, waiting, and polling-based blocking, with documentation of the multi-thread limitation and suggested correction.
Circular buffer thread flow
test/producer-consumer/producer-consumer.c
Adds a size-two circular buffer coordinated by producer and consumer threads through two semaphores and a mutex.
Build and debugging targets
test/producer-consumer/Makefile
Adds compilation, execution, debugger, editor, cleanup, and distribution targets.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Suggested reviewers: aayushi363, gc00

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: adding a producer-consumer example to the repository.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch livelock

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (1)
test/producer-consumer/Makefile (1)

9-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Declare command targets as phony.

If a file or directory named run or clean exists, Make may skip these recipes. Add .PHONY declarations for all command targets.

+.PHONY: run gdb vi emacs clean dist
+
 run: $(FILE)

Also applies to: 25-26

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/producer-consumer/Makefile` at line 9, Declare the Makefile command
targets, including run and clean, as phony using a .PHONY declaration so their
recipes always execute even when matching files or directories exist.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/launch.c`:
- Around line 120-122: Update the inline -lc option handling near
ENV_MAX_LIVELOCK_CYCLE_LIMIT to validate the entire numeric suffix, not just its
first character, before calling setenv. Reuse the validator used by the
separated-form argument when available, and reject values such as -lc12x rather
than storing them.

In `@test/producer-consumer/Makefile`:
- Around line 12-14: Update the $(FILE) target prerequisites in the Makefile to
include partial-solution.c alongside $(FILE).c, while leaving the existing
compilation recipe unchanged.
- Line 9: Update the Makefile’s run target so it executes the built $(FILE)
binary after ensuring $(FILE) is built, rather than only declaring it as a
prerequisite. Preserve the existing build dependency and use the project’s
established executable invocation convention if available.

In `@test/producer-consumer/partial-solution.c`:
- Around line 22-53: Rename the custom semaphore API from sem_* to mysem_* so
McMini recognizes the intended implementation. In
test/producer-consumer/partial-solution.c:22-53, rename sem_t and
sem_init/sem_wait/sem_post; update the corresponding type declarations and
prototypes in test/producer-consumer/producer-consumer.c:36-47, initialization
at :97-98, producer calls at :122-127, and consumer calls at :136-141. Correct
the API statement in test/producer-consumer/000-README:5-8 to match the renamed
interface.
- Around line 29-33: Update the third parameter of sem_init in
partial-solution.c from int to unsigned int so its definition matches the
producer-consumer.c declaration and preserves the expected ABI contract when
initializing sem->count.

---

Nitpick comments:
In `@test/producer-consumer/Makefile`:
- Line 9: Declare the Makefile command targets, including run and clean, as
phony using a .PHONY declaration so their recipes always execute even when
matching files or directories exist.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e8a21404-83c6-4d23-9715-bd7434bc97ad

📥 Commits

Reviewing files that changed from the base of the PR and between f8403bc and 7da3bed.

📒 Files selected for processing (5)
  • src/launch.c
  • test/producer-consumer/000-README
  • test/producer-consumer/Makefile
  • test/producer-consumer/partial-solution.c
  • test/producer-consumer/producer-consumer.c

Comment thread src/launch.c
Comment on lines +120 to +122
else if (cur_arg[0][1] == 'l' && cur_arg[0][2] == 'c' &&
isdigit(cur_arg[0][3])) {
setenv(ENV_MAX_LIVELOCK_CYCLE_LIMIT, cur_arg[0] + 3, 1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject malformed -lc<num> values instead of silently truncating them.

The branch validates only the first suffix character, so -lc12x stores 12x; downstream strtoul(..., 10) then consumes the 12 prefix and silently applies the wrong limit. Validate that the entire suffix is numeric before calling setenv, ideally sharing the same validator with the separated form.

Proposed validation
 else if (cur_arg[0][1] == 'l' && cur_arg[0][2] == 'c' &&
       isdigit(cur_arg[0][3])) {
+      char *endptr;
+      strtol(cur_arg[0] + 3, &endptr, 10);
+      if (endptr[0] != '\0') {
+        fprintf(stderr, "%s: illegal value\n",
+                "--max-livelock-cycle-limit");
+        exit(1);
+      }
       setenv(ENV_MAX_LIVELOCK_CYCLE_LIMIT, cur_arg[0] + 3, 1);
       cur_arg++;
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
else if (cur_arg[0][1] == 'l' && cur_arg[0][2] == 'c' &&
isdigit(cur_arg[0][3])) {
setenv(ENV_MAX_LIVELOCK_CYCLE_LIMIT, cur_arg[0] + 3, 1);
else if (cur_arg[0][1] == 'l' && cur_arg[0][2] == 'c' &&
isdigit(cur_arg[0][3])) {
char *endptr;
strtol(cur_arg[0] + 3, &endptr, 10);
if (endptr[0] != '\0') {
fprintf(stderr, "%s: illegal value\n",
"--max-livelock-cycle-limit");
exit(1);
}
setenv(ENV_MAX_LIVELOCK_CYCLE_LIMIT, cur_arg[0] + 3, 1);
cur_arg++;
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/launch.c` around lines 120 - 122, Update the inline -lc option handling
near ENV_MAX_LIVELOCK_CYCLE_LIMIT to validate the entire numeric suffix, not
just its first character, before calling setenv. Reuse the validator used by the
separated-form argument when available, and reject values such as -lc12x rather
than storing them.

CFLAGS += -g3 -O0
LDLIBS += -lpthread

run: $(FILE)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make run actually execute the example.

run only builds $(FILE); make run never launches the producer-consumer program.

Proposed fix
 run: $(FILE)
+	./$(FILE)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
run: $(FILE)
run: $(FILE)
./$(FILE)
🧰 Tools
🪛 checkmake (0.3.2)

[warning] 9-9: Target "run" should be declared PHONY.

(phonydeclared)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/producer-consumer/Makefile` at line 9, Update the Makefile’s run target
so it executes the built $(FILE) binary after ensuring $(FILE) is built, rather
than only declaring it as a prerequisite. Preserve the existing build dependency
and use the project’s established executable invocation convention if available.

Comment on lines +12 to +14
$(FILE): $(FILE).c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ \
$(FILE).c partial-solution.c $(LDLIBS)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Track partial-solution.c as a build prerequisite.

The recipe compiles partial-solution.c, but the target only depends on producer-consumer.c. Changes to the semaphore implementation therefore leave the executable stale until a manual clean or forced rebuild.

Proposed fix
-$(FILE): $(FILE).c
+$(FILE): $(FILE).c partial-solution.c
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$(FILE): $(FILE).c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ \
$(FILE).c partial-solution.c $(LDLIBS)
$(FILE): $(FILE).c partial-solution.c
$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ \
$(FILE).c partial-solution.c $(LDLIBS)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/producer-consumer/Makefile` around lines 12 - 14, Update the $(FILE)
target prerequisites in the Makefile to include partial-solution.c alongside
$(FILE).c, while leaving the existing compilation recipe unchanged.

Comment on lines +22 to +53
struct sem {
int count;
pthread_mutex_t mutex;
};
typedef struct sem sem_t;
// Unlike Java, C/C++ require a semicolon to end the 'struct sem' statement.

int sem_init(sem_t *sem, int ignore, int init) {
sem->count = init;
// Anybody who wants to use sem->count should acquire this lock first.
pthread_mutex_init(&(sem->mutex), NULL); // See 'man pthread_mutex_init'
}

int sem_post(sem_t *sem) {
pthread_mutex_lock( &(sem->mutex) );
sem->count += 1;
pthread_mutex_unlock( &(sem->mutex) );
}

void block(sem_t *sem); // Used by sem_wait()

int sem_wait(sem_t *sem) {
pthread_mutex_lock( &(sem->mutex) );
sem->count -= 1;
if (sem->count < 0) {
// We must release lock, or no one can ever call sem_post() for us.
pthread_mutex_unlock( &(sem->mutex) );
block(sem);
pthread_mutex_lock( &(sem->mutex) );
}
pthread_mutex_unlock( &(sem->mutex) );
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Rename the custom semaphore API before running under McMini.

The README says McMini requires mysem_*, but the implementation and harness still use sem_*; McMini will model the custom calls as real semaphore operations rather than expose the intended blocking bug.

  • test/producer-consumer/partial-solution.c#L22-L53: rename sem_t and sem_init/sem_wait/sem_post to a custom mysem_* API.
  • test/producer-consumer/producer-consumer.c#L36-L47: update the type and prototypes to the renamed API.
  • test/producer-consumer/producer-consumer.c#L97-L98: initialize the renamed semaphores.
  • test/producer-consumer/producer-consumer.c#L122-L127: update producer wait/post calls.
  • test/producer-consumer/producer-consumer.c#L136-L141: update consumer wait/post calls.
  • test/producer-consumer/000-README#L5-L8: correct the statement once the rename is applied.
📍 Affects 3 files
  • test/producer-consumer/partial-solution.c#L22-L53 (this comment)
  • test/producer-consumer/producer-consumer.c#L36-L47
  • test/producer-consumer/producer-consumer.c#L97-L98
  • test/producer-consumer/producer-consumer.c#L122-L127
  • test/producer-consumer/producer-consumer.c#L136-L141
  • test/producer-consumer/000-README#L5-L8
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/producer-consumer/partial-solution.c` around lines 22 - 53, Rename the
custom semaphore API from sem_* to mysem_* so McMini recognizes the intended
implementation. In test/producer-consumer/partial-solution.c:22-53, rename sem_t
and sem_init/sem_wait/sem_post; update the corresponding type declarations and
prototypes in test/producer-consumer/producer-consumer.c:36-47, initialization
at :97-98, producer calls at :122-127, and consumer calls at :136-141. Correct
the API statement in test/producer-consumer/000-README:5-8 to match the renamed
interface.

Comment on lines +29 to +33
int sem_init(sem_t *sem, int ignore, int init) {
sem->count = init;
// Anybody who wants to use sem->count should acquire this lock first.
pthread_mutex_init(&(sem->mutex), NULL); // See 'man pthread_mutex_init'
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu
rg -nP '^\s*int\s+sem_init\s*\(' \
  test/producer-consumer/partial-solution.c \
  test/producer-consumer/producer-consumer.c

Repository: mcminickpt/mcmini

Length of output: 354


🏁 Script executed:

#!/bin/sh
set -eu
printf '--- partial-solution.c ---\n'
cat -n test/producer-consumer/p_partial-solution.c 2>/dev/null || cat -n test/producer-consumer/partial-solution.c | sed -n '1,80p'
printf '\n--- producer-consumer.c relevant lines ---\n'
cat -n test/producer-consumer/producer-consumer.c | sed -n '1,80p'
printf '\n--- header references ---\n'
rg -n 'sem_init|sem_t' test/producer-consumer -C 2

Repository: mcminickpt/mcmini

Length of output: 246


🏁 Script executed:

#!/bin/sh
set -eu
printf '%s\n' '--- partial-solution.c ---'
cat -n test/producer-consumer/partial-solution.c | sed -n '1,80p'
printf '%s\n' ''
printf '%s\n' '--- producer-consumer.c relevant lines ---'
cat -n test/producer-consumer/producer-consumer.c | sed -n '1,80p'
printf '%s\n' ''
printf '%s\n' '--- header references ---'
rg -n 'sem_init|sem_t' test/producer-consumer -C 2

Repository: mcminickpt/mcmini

Length of output: 12096


Fix sem_init()’s third parameter type.

producer-consumer.c declares the third argument as unsigned int value, but partial-solution.c defines it as int init. The definition must match the declaration from the same ABI contract, so sem->count is not incorrectly initialized by values outside the range expected by the caller.

Proposed fix
-int sem_init(sem_t *sem, int ignore, int init) {
+int sem_init(sem_t *sem, int ignore, unsigned int init) {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
int sem_init(sem_t *sem, int ignore, int init) {
sem->count = init;
// Anybody who wants to use sem->count should acquire this lock first.
pthread_mutex_init(&(sem->mutex), NULL); // See 'man pthread_mutex_init'
}
int sem_init(sem_t *sem, int ignore, unsigned int init) {
sem->count = init;
// Anybody who wants to use sem->count should acquire this lock first.
pthread_mutex_init(&(sem->mutex), NULL); // See 'man pthread_mutex_init'
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/producer-consumer/partial-solution.c` around lines 29 - 33, Update the
third parameter of sem_init in partial-solution.c from int to unsigned int so
its definition matches the producer-consumer.c declaration and preserves the
expected ABI contract when initializing sem->count.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant