Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Custom compiler crash/panic handler #731

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 92 additions & 1 deletion effekt/jvm/src/main/scala/effekt/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ trait Driver extends kiama.util.Compiler[EffektConfig, EffektError] { outer =>
case e @ CompilerPanic(msg) =>
context.report(msg)
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved
e.getStackTrace.foreach { line =>
context.info(" at " + line)
generateCrashReport(e, context, config)
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved
}
// when in server-mode, do not crash but report the error to avoid
// restarting the server.
Expand All @@ -108,6 +108,97 @@ trait Driver extends kiama.util.Compiler[EffektConfig, EffektError] { outer =>
afterCompilation(source, config)(context)
}

def generateCrashReport(e: Throwable, context: Context, config: EffektConfig): Unit = {
import java.nio.file.{Files, Paths}
import java.util.Properties

// Capture general information
val effektVersion = effekt.util.Version.effektVersion
val osInfo = System.getProperty("os.name") +
" (" + System.getProperty("os.arch") + ") " +
System.getProperty("os.version")

val jvmInfo = System.getProperty("java.version") +
" (" + System.getProperty("java.vendor") + ")"
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved

val stackTrace = e.getStackTrace.map(line => " at " + line.toString).mkString("\n")
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved

// Collect backend details (if applicable)
val backendInfoName = config.backend() match {
case Backend(name, compiler, runner) => name
case null => s"Backend-specific info Name not retrievable"
}
val backendInfoCompiler = config.backend() match {
case Backend(name, compiler, runner) => compiler
case null => s"Backend-specific info Compiler not retrievable"
}
val backendInfoRunner = config.backend() match {
case Backend(name, compiler, runner) => runner
case null => s"Backend-specific info Runner not retrievable"
}
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved

// Construct the report
val report =
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved
s"""|=== Effekt Compiler Crash Report ===
|
|Where to report: https://github.com/effekt-lang/effekt/issues
|
|
|Effekt Compiler Version: $effektVersion
|
|Backend-specific info:
| - Name: $backendInfoName
| - Compiler: $backendInfoCompiler
| - Runner: $backendInfoRunner
|
|Operating System: $osInfo
|
|JVM Version: $jvmInfo
|
|Full Stack Trace:
|$stackTrace
|""".stripMargin

val mdReport =
s"""|# === Effekt Compiler Crash Report ===
|
|**Where to report**: [https://github.com/effekt-lang/effekt/issues](https://github.com/effekt-lang/effekt/issues)
|
|---
|## Compiler Details
|
|- **Effekt Compiler Version**: $effektVersion
|- **Backend-specific info**:
| - **Name**: $backendInfoName
| - **Compiler**: $backendInfoCompiler
| - **Runner**: $backendInfoRunner
|
|- **Operating System**: $osInfo
|
|- **JVM Version**: $jvmInfo
|
|
|# Full Stack Trace:
|```
|$stackTrace
|```
|""".stripMargin

// Print the report to console
context.info(report)

// write to a markdown file in ./out/
try {
val outputPath = Paths.get("./out/crash-report.md")
JakubSchwenkbeck marked this conversation as resolved.
Show resolved Hide resolved
Files.createDirectories(outputPath.getParent)
Files.write(outputPath, mdReport.getBytes)
context.info(s"Crash report saved to: $outputPath")
} catch {
case ex: Exception =>
context.info("Failed to save crash report to file: " + ex.getMessage)
}
}

/**
* Outputs the timing information captured in [[effekt.util.Timers]] by [[effekt.context.Context]]. Either a JSON file
* is written to disk or a plain text message is written to stdout.
Expand Down
Loading