Skip to content

Commit eff0760

Browse files
committed
fix: do not expose to native scala-allocated object since they may be collected and cause segfaults
1 parent 62c00de commit eff0760

File tree

11 files changed

+53
-82
lines changed

11 files changed

+53
-82
lines changed

scafi3-integration/src/test/resources/c/main.template.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ bool on_result(const void* result) {
3232
int main(void) {
3333
Neighborhood neighbors = Neighborhood_empty();
3434
{{ neighbors }}
35-
ConnectionOrientedNetworkManager network = socket_network(device({{ deviceId }}), {{ port }}, neighbors);
36-
engine(network, aggregate_program, on_result);
35+
engine(device({{ deviceId }}), {{ port }}, neighbors, aggregate_program, on_result);
3736
printf("%s", field_to_str((const Field*) last_round_result));
3837
return 0;
3938
}

scafi3-integration/src/test/resources/js/app.template.mjs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,10 @@ const { Runtime, returning, returnSending } = await import("./main.mjs");
99
const deviceId = {{ deviceId }};
1010
const port = {{ port }};
1111
const neighbors = new Map({{ neighbors }});
12-
const network = Runtime.socketNetwork(deviceId, port, neighbors);
1312

1413
let lastResult = null;
1514
let iterations = 10;
16-
await Runtime.engine(network, lang => aggregateProgram(lang), async result => {
15+
await Runtime.engine(deviceId, port, neighbors, lang => aggregateProgram(lang), async result => {
1716
lastResult = result;
1817
await sleep(1_000);
1918
return iterations-- > 0;

scafi3-mp-api/js-jvm/src/main/scala/it/unibo/scafi/runtime/NoMemorySafeContext.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
package it.unibo.scafi.runtime
2+
import it.unibo.scafi.types.MemorySafeContext
23

34
/**
45
* A context where memory safety is enforced by construction by the underlying platform (e.g., JVM, JavaScript).

scafi3-mp-api/js/src/main/scala/it/unibo/scafi/runtime/JSScafiRuntime.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ import io.github.iltotore.iron.refineUnsafe
1313
import scafi.context.xc.ExchangeAggregateContext
1414
import scafi.message.UniversalCodable
1515
import scafi.message.JSBinaryCodable.jsBinaryCodable
16-
import scafi.runtime.bindings.{ ScafiEngineBinding, ScafiNetworkBinding }
16+
import scafi.runtime.bindings.ScafiEngineBinding
1717
import scafi.libraries.FullLibrary
1818

1919
@SuppressWarnings(Array("scalafix:DisableSyntax.asInstanceOf"))
20-
object JSScafiRuntime extends PortableRuntime with ScafiNetworkBinding with ScafiEngineBinding with JSTypes:
20+
object JSScafiRuntime extends PortableRuntime with ScafiEngineBinding with JSTypes:
2121

2222
given ExecutionContext = scalajs.concurrent.JSExecutionContext.Implicits.queue
2323

@@ -44,5 +44,5 @@ object JSScafiRuntime extends PortableRuntime with ScafiNetworkBinding with Scaf
4444
override def library[ID](using Arena): ExchangeAggregateContext[ID] ?=> FullLibrary = FullLibrary()
4545

4646
@JSExportTopLevel("Runtime")
47-
object JSAPI extends Api with NetworkBindings with EngineBindings with JSRequirements
47+
object JSAPI extends Api with EngineBindings with JSRequirements
4848
end JSScafiRuntime

scafi3-mp-api/native/src/main/resources/include/runtime.h

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,17 @@
44
#include <stdbool.h>
55
#include "libraries.h"
66

7-
typedef struct ConnectionOrientedNetworkManagerImpl* ConnectionOrientedNetworkManager;
8-
97
struct Endpoint {
108
char* address;
119
int port;
1210
};
1311

1412
MAP_OF(Neighborhood, DeviceId, struct Endpoint*)
1513

16-
ConnectionOrientedNetworkManager socket_network(
14+
void engine(
1715
const BinaryCodable* device_id,
1816
int port,
19-
const Neighborhood neighbors
20-
);
21-
22-
void engine(
23-
const ConnectionOrientedNetworkManager network_manager,
17+
const Neighborhood neighbors,
2418
const void* (*aggregate_program)(const AggregateLibrary* library),
2519
bool (*on_result)(const void* result)
2620
);

scafi3-mp-api/native/src/main/scala/it/unibo/scafi/runtime/NativeMemoryContext.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package it.unibo.scafi.runtime
22

33
import scala.scalanative.unsafe.Zone
44

5+
import it.unibo.scafi.types.MemorySafeContext
6+
57
/**
68
* A memory-safe context implementation for native platforms using `Zone` for scoped memory management.
79
*/

scafi3-mp-api/native/src/main/scala/it/unibo/scafi/runtime/NativeScafiRuntime.scala

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@ import it.unibo.scafi.nativebindings.structs.{
1616
BinaryCodable as CBinaryCodable,
1717
Endpoint as CEndpoint,
1818
}
19-
import it.unibo.scafi.runtime.bindings.{ ScafiEngineBinding, ScafiNetworkBinding }
20-
import it.unibo.scafi.runtime.network.sockets.{ ConnectionOrientedNetworkManager, InetTypes }
19+
import it.unibo.scafi.runtime.bindings.ScafiEngineBinding
20+
import it.unibo.scafi.runtime.network.sockets.InetTypes
2121
import it.unibo.scafi.types.{ EqWrapper, NativeTypes }
2222

2323
import io.github.iltotore.iron.refineUnsafe
2424

2525
@SuppressWarnings(Array("scalafix:DisableSyntax.asInstanceOf"))
26-
object NativeScafiRuntime extends PortableRuntime with ScafiNetworkBinding with ScafiEngineBinding with NativeTypes:
26+
object NativeScafiRuntime extends PortableRuntime with ScafiEngineBinding with NativeTypes:
2727

2828
given ExecutionContext = ExecutionContext.fromExecutor(Executors.newCachedThreadPool())
2929

@@ -50,19 +50,14 @@ object NativeScafiRuntime extends PortableRuntime with ScafiNetworkBinding with
5050

5151
override def library[ID](using Arena): ExchangeAggregateContext[ID] ?=> AggregateLibrary = FullLibrary().asNative
5252

53-
object NativeApi extends Api with NativeAdts with NetworkBindings with EngineBindings with NativeRequirements:
53+
object NativeApi extends Api with NativeAdts with EngineBindings with NativeRequirements:
5454

55-
@exported("socket_network")
56-
def nativeSocketNetwork(
55+
@exported("engine")
56+
def nativeEngine(
5757
deviceId: CVoidPtr,
5858
port: CInt,
5959
neighbors: Map[CVoidPtr, Endpoint],
60-
): ConnectionOrientedNetworkManager[DeviceId] = socketNetwork[CVoidPtr](deviceId, port, neighbors)
61-
62-
@exported("engine")
63-
def nativeEngine(
64-
network: ConnectionOrientedNetworkManager[DeviceId],
6560
program: Function1[AggregateLibrary, CVoidPtr],
6661
onResult: Function1[CVoidPtr, Outcome[Boolean]],
67-
): Outcome[Unit] = engine(network, program, onResult)
62+
): Outcome[Unit] = engine(deviceId, port, neighbors, program, onResult)
6863
end NativeScafiRuntime

scafi3-mp-api/shared/src/main/scala/it/unibo/scafi/runtime/PortableRuntime.scala

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package it.unibo.scafi.runtime
22

3-
import it.unibo.scafi
4-
import it.unibo.scafi.types.PortableTypes
5-
6-
import scafi.context.xc.ExchangeAggregateContext
7-
import scafi.message.UniversalCodable
8-
import scafi.runtime.network.sockets.ConnectionOrientedNetworkManager
3+
import it.unibo.scafi.context.xc.ExchangeAggregateContext
4+
import it.unibo.scafi.message.UniversalCodable
5+
import it.unibo.scafi.runtime.network.sockets.InetTypes
6+
import it.unibo.scafi.types.{ MemorySafeContext, PortableTypes }
97

108
/**
119
* Portable runtime API entry point.
@@ -27,8 +25,8 @@ trait PortableRuntime:
2725
/** A network endpoint consisting of an [[address]] and a [[port]]. */
2826
type Endpoint
2927

30-
/** Endpoint is isomorphic to [[scafi.runtime.network.sockets.InetTypes.Endpoint]]. */
31-
given toInetEndpoint: Conversion[Endpoint, scafi.runtime.network.sockets.InetTypes.Endpoint] = compiletime.deferred
28+
/** Endpoint is isomorphic to [[InetTypes.Endpoint]]. */
29+
given toInetEndpoint: Conversion[Endpoint, InetTypes.Endpoint] = compiletime.deferred
3230

3331
/** The requirements that must be satisfied by any concrete implementation of the runtime. */
3432
trait Requirements extends MemorySafeContext:
@@ -44,22 +42,25 @@ trait PortableRuntime:
4442
trait Api:
4543
self: Requirements & Adts =>
4644

47-
/** @return a socket-based network working on [[port]] with statically assigned [[neighbors]] and [[deviceId]]. */
45+
/**
46+
* Portable entry point for Scafi3 aggregate programs in a distributed environment with socket-based networking.
47+
* @param deviceId
48+
* the unique identifier of the device
49+
* @param port
50+
* the port on which the device listens for incoming messages
51+
* @param neighbors
52+
* a map of neighboring device IDs to their network endpoints
53+
* @param program
54+
* the aggregate program to run on the device
55+
* @param onResult
56+
* a callback to handle the result of the program execution returning an Outcome of Boolean indicating whether to
57+
* continue or stop
58+
*/
4859
@JSExport
49-
def socketNetwork[ID](
60+
def engine[ID, Result](
5061
deviceId: ID,
5162
port: Int,
5263
neighbors: Map[ID, Endpoint],
53-
): ConnectionOrientedNetworkManager[DeviceId]
54-
55-
/**
56-
* Runs the given aggregate [[program]] on the device with the given [[deviceId]], using the provided [[network]].
57-
* The result of the program is passed to the [[onResult]] callback, which should return an [[Outcome]] indicating
58-
* whether the execution needs to continue or stop.
59-
*/
60-
@JSExport
61-
def engine[Result](
62-
network: ConnectionOrientedNetworkManager[DeviceId],
6364
program: Function1[AggregateLibrary, Result],
6465
onResult: Function1[Result, Outcome[Boolean]],
6566
): Outcome[Unit]

scafi3-mp-api/shared/src/main/scala/it/unibo/scafi/runtime/bindings/ScafiEngineBinding.scala

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@ import scala.util.{ Failure, Try }
55

66
import it.unibo.scafi.context.xc.ExchangeAggregateContext.exchangeContextFactory
77
import it.unibo.scafi.runtime.{ PortableRuntime, ScafiEngine }
8-
import it.unibo.scafi.runtime.network.sockets.ConnectionOrientedNetworkManager
8+
import it.unibo.scafi.runtime.network.sockets.{ ConnectionConfiguration, SocketNetworkManager }
99
import it.unibo.scafi.types.PortableTypes
1010

11+
import io.github.iltotore.iron.refineUnsafe
12+
1113
/**
1214
* Provides a concrete implementation of the portable runtime API for the ScaFi engine.
1315
*/
@@ -19,11 +21,15 @@ trait ScafiEngineBinding extends PortableRuntime:
1921

2022
/* WARNING: Inline is needed here for native platform to ensure function pointers are correctly handled at
2123
* call site. Removing it does not lead to compilation errors but to runtime segfaults! */
22-
inline override def engine[Result](
23-
network: ConnectionOrientedNetworkManager[DeviceId],
24+
inline override def engine[ID, Result](
25+
deviceId: ID,
26+
port: Int,
27+
neighbors: Map[ID, Endpoint],
2428
program: Function1[AggregateLibrary, Result],
2529
onResult: Function1[Result, Outcome[Boolean]],
2630
): Outcome[Unit] =
31+
deviceIdCodable.register(deviceId)
32+
val network = socketNetwork(deviceId, port, neighbors)
2733
network
2834
.start()
2935
.flatMap: _ =>
@@ -32,6 +38,11 @@ trait ScafiEngineBinding extends PortableRuntime:
3238
.andThen(_ => Future(network.close()))
3339
.andThen(reportAnyFailure)
3440

41+
private def socketNetwork[ID](deviceId: ID, port: Int, neighbors: Map[ID, Endpoint]) =
42+
given ConnectionConfiguration = ConnectionConfiguration.basic
43+
val devicesNet = neighbors.view.map((id, e) => (id: DeviceId, toInetEndpoint(e))).toMap
44+
SocketNetworkManager.withFixedNeighbors(deviceId: DeviceId, port.refineUnsafe, devicesNet)
45+
3546
private val reportAnyFailure: PartialFunction[Try[Unit], Unit] =
3647
case Failure(err) => Console.err.println(s"Error occurred: ${err.getMessage}")
3748
end EngineBindings

scafi3-mp-api/shared/src/main/scala/it/unibo/scafi/runtime/bindings/ScafiNetworkBinding.scala

Lines changed: 0 additions & 31 deletions
This file was deleted.

0 commit comments

Comments
 (0)