Skip to content

Commit 44b08cc

Browse files
abossardCopilot
andcommitted
Add 5s timeout to code generation exec() — prevents infinite loops
Both compilation and test execution are wrapped with signal.alarm(5). If generated code runs too long (infinite loop), it times out cleanly with '❌ Timeout: Code läuft zu lange (Endlosschleife?)'. NB01 verified: executes headless without errors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6007dbc commit 44b08cc

4 files changed

Lines changed: 645 additions & 71 deletions

File tree

notebooks/01_evaluation_and_tuning.ipynb

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,51 @@
11381138
" ✅ flatten([1, [2], 3]) → [1, 2, 3]\n",
11391139
" ✅ flatten([1, [2, [3, [4]]]]) → [1, 2, 3, 4]\n",
11401140
"\n",
1141-
"📝 Aufgabe: Write a function that counts the frequency of each word in a string and returns \n"
1141+
"📝 Aufgabe: Write a function that counts the frequency of each word in a string and returns \n",
1142+
" Generierter Code:\n",
1143+
" │ def word_frequency(string):\n",
1144+
" │ # Split the string into words\n",
1145+
" │ words = string.split()\n",
1146+
" │ # Create a dictionary to store word counts\n",
1147+
" │ frequency = {}\n",
1148+
" │ # Count the frequency of each word\n",
1149+
" │ for word in words:\n",
1150+
" │ # Convert to lowercase to count \"Word\" and \"word\" as the same\n",
1151+
" │ ... (18 Zeilen)\n",
1152+
"{'hello': 2, 'world': 1}\n",
1153+
" ✅ word_frequency('the cat sat on the mat') → {'the': 2, 'cat': 1, 'sat': 1, 'on': 1, 'mat': 1}\n",
1154+
"\n",
1155+
"📝 Aufgabe: Write a function that removes duplicate elements from a list while preserving th\n",
1156+
" Generierter Code:\n",
1157+
" │ def remove_duplicates(input_list):\n",
1158+
" │ seen = set()\n",
1159+
" │ result = []\n",
1160+
" │ for item in input_list:\n",
1161+
" │ if item not in seen:\n",
1162+
" │ seen.add(item)\n",
1163+
" │ result.append(item)\n",
1164+
" │ return result\n",
1165+
" │ ... (12 Zeilen)\n",
1166+
"[1, 2, 3, 4, 5]\n",
1167+
" ✅ remove_duplicates([1, 2, 3, 2, 1, 4]) → [1, 2, 3, 4]\n",
1168+
"\n",
1169+
"📝 Aufgabe: Write a function that evaluates a mathematical expression string containing inte\n",
1170+
" Generierter Code:\n",
1171+
" │ def evaluate_expression(expression: str) -> float:\n",
1172+
" │ def precedence(op):\n",
1173+
" │ if op in ('+', '-'):\n",
1174+
" │ return 1\n",
1175+
" │ if op in ('*', '/'):\n",
1176+
" │ return 2\n",
1177+
" │ return 0\n",
1178+
"\n",
1179+
" │ ... (69 Zeilen)\n",
1180+
"-27.0\n",
1181+
" ✅ eval_expr('3 + 4 * 2') → 11.0\n",
1182+
" ✅ eval_expr('(1 + 2) * (3 + 4)') → 21.0\n",
1183+
" ✅ eval_expr('10 / 3') → 3.3333333333333335\n",
1184+
" ✅ eval_expr('2 * 3 + 4 * 5') → 26.0\n",
1185+
" ✅ eval_expr('(2 + 3) * (7 - 4) / 5') → 3.0\n"
11421186
]
11431187
}
11441188
],
@@ -1210,8 +1254,22 @@
12101254
" # Generierte Funktion ausführen\n",
12111255
" gen_ns = {}\n",
12121256
" try:\n",
1257+
" import signal\n",
1258+
" def _timeout_handler(signum, frame):\n",
1259+
" raise TimeoutError('Code execution took too long (possible infinite loop)')\n",
1260+
" old_handler = signal.signal(signal.SIGALRM, _timeout_handler)\n",
1261+
" signal.alarm(5) # 5 second timeout\n",
12131262
" exec(compile(code, '<generated>', 'exec'), gen_ns)\n",
1263+
" signal.alarm(0) # cancel timeout\n",
1264+
" signal.signal(signal.SIGALRM, old_handler)\n",
1265+
" except TimeoutError:\n",
1266+
" signal.alarm(0)\n",
1267+
" print(f\" ❌ Timeout: Code läuft zu lange (Endlosschleife?)\")\n",
1268+
" tasks_error += 1\n",
1269+
" print()\n",
1270+
" continue\n",
12141271
" except Exception as e:\n",
1272+
" signal.alarm(0)\n",
12151273
" print(f\" ❌ Kompilierung fehlgeschlagen: {type(e).__name__}: {e}\")\n",
12161274
" tasks_error += 1\n",
12171275
" print()\n",
@@ -1253,8 +1311,11 @@
12531311
" task_ok = True\n",
12541312
" for args in test_inputs:\n",
12551313
" try:\n",
1314+
" signal.signal(signal.SIGALRM, _timeout_handler)\n",
1315+
" signal.alarm(5)\n",
12561316
" expected = ref_func(*args)\n",
12571317
" got = gen_func(*args)\n",
1318+
" signal.alarm(0)\n",
12581319
" # Für Floats: Toleranz-Vergleich\n",
12591320
" if isinstance(expected, float) and isinstance(got, (int, float)):\n",
12601321
" match = abs(float(got) - expected) < 1e-6\n",
@@ -1606,4 +1667,4 @@
16061667
},
16071668
"nbformat": 4,
16081669
"nbformat_minor": 5
1609-
}
1670+
}

0 commit comments

Comments
 (0)