@@ -169,12 +169,77 @@ for (int i = 0; i < e_shnum; i++)
169169 WU64(newData, newSh + 24, translate(RU64(data, oldSh + 24))); // sh_offset
170170}
171171
172- // ── Write patched file ──────────────────────────────────────────────
173- System.IO.File.WriteAllBytes(FilePath, newData);
174- WasPatched = true;
175- Log.LogMessage(MessageImportance.High,
176- "PatchElfPageSize: patched {0} (align 0x1000 -> 0x{1:X}, +{2} bytes)",
177- System.IO.Path.GetFileName(FilePath), pageSize, newData.Length - data.Length);
172+ // ── Write patched file (with lock to handle parallel builds) ────────
173+ string lockFile = FilePath + ".patch-lock";
174+ System.IO.FileStream lockStream = null;
175+ try
176+ {
177+ // Acquire an exclusive lock file to prevent concurrent writes.
178+ // Retry up to 30 times with 1-second delays (handles parallel MSBuild nodes).
179+ for (int attempt = 0; attempt < 30; attempt++)
180+ {
181+ try
182+ {
183+ lockStream = new System.IO.FileStream(lockFile,
184+ System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite,
185+ System.IO.FileShare.None);
186+ break;
187+ }
188+ catch (System.IO.IOException)
189+ {
190+ System.Threading.Thread.Sleep(1000);
191+ }
192+ }
193+
194+ if (lockStream == null)
195+ {
196+ Log.LogMessage(MessageImportance.High,
197+ "PatchElfPageSize: could not acquire lock for {0}, skipping (another build node may be patching it)",
198+ System.IO.Path.GetFileName(FilePath));
199+ return true;
200+ }
201+
202+ // Re-read and re-check: another node may have already patched while we waited.
203+ byte[] freshData = System.IO.File.ReadAllBytes(FilePath);
204+ bool stillNeeds = false;
205+ if (freshData.Length >= 64 && freshData[0] == 0x7F && freshData[4] == 2 && freshData[5] == 1)
206+ {
207+ ulong freshPhoff = RU64(freshData, 32);
208+ int freshPhentsz = (int)(freshData[54] | (freshData[55] << 8));
209+ int freshPhnum = (int)(freshData[56] | (freshData[57] << 8));
210+ for (int i = 0; i < freshPhnum; i++)
211+ {
212+ int h = (int)freshPhoff + i * freshPhentsz;
213+ if (RU32(freshData, h) == PT_LOAD && RU64(freshData, h + 48) < (ulong)pageSize)
214+ {
215+ stillNeeds = true;
216+ break;
217+ }
218+ }
219+ }
220+
221+ if (!stillNeeds)
222+ {
223+ Log.LogMessage(MessageImportance.Low,
224+ "PatchElfPageSize: {0} was already patched by another build node",
225+ System.IO.Path.GetFileName(FilePath));
226+ return true;
227+ }
228+
229+ System.IO.File.WriteAllBytes(FilePath, newData);
230+ WasPatched = true;
231+ Log.LogMessage(MessageImportance.High,
232+ "PatchElfPageSize: patched {0} (align 0x1000 -> 0x{1:X}, +{2} bytes)",
233+ System.IO.Path.GetFileName(FilePath), pageSize, newData.Length - data.Length);
234+ }
235+ finally
236+ {
237+ if (lockStream != null)
238+ {
239+ lockStream.Dispose();
240+ try { System.IO.File.Delete(lockFile); } catch { }
241+ }
242+ }
178243]]> </Code >
179244 </Task >
180245 </UsingTask >
0 commit comments